Initial checkin of Pika from heckimp
159
devel-docs/HACKING.md
Normal file
@ -0,0 +1,159 @@
|
||||
# Building from git and contributing
|
||||
|
||||
While packagers are expected to compile PIKA from tarballs (same for
|
||||
personal usage), developers who wish to contribute patches should
|
||||
compile from the git repository.
|
||||
|
||||
The procedure is basically the same (such as described in the `INSTALL`
|
||||
file, which you will notice doesn't exist in the repository; you can
|
||||
find [INSTALL.in](/INSTALL.in) instead, whose base text is the same
|
||||
before substitution by the build configuration step). Yet it has a few
|
||||
extra steps.
|
||||
|
||||
## Git
|
||||
|
||||
PIKA is available from GNOME Git. You can use the following commands
|
||||
to get PIKA from the the git server:
|
||||
|
||||
$ git clone https://gitlab.gnome.org/GNOME/pika.git
|
||||
|
||||
You can read more on using GNOME's git service at these URLs:
|
||||
|
||||
https://wiki.gnome.org/Git
|
||||
https://www.kernel.org/pub/software/scm/git/docs/
|
||||
|
||||
|
||||
The development branches of PIKA closely follow the development branches
|
||||
of `babl` and `GEGL` which are considered part of the project. Therefore
|
||||
you will also have to clone and build these repositories:
|
||||
|
||||
$ git clone https://gitlab.gnome.org/GNOME/babl.git
|
||||
$ git clone https://gitlab.gnome.org/GNOME/gegl.git
|
||||
|
||||
|
||||
As for other requirements as listed in the `INSTALL` file, if you use
|
||||
a development-oriented Linux distribution (Debian Testing or Fedora for
|
||||
instance), you will often be able to install all of them from your
|
||||
package manager. On Windows, the MSYS2 project is great for keeping up
|
||||
with libraries too. On macOS, it is unfortunately much more of a hurdle
|
||||
and you should probably look at instructions in our [pika-macos-build
|
||||
repository](https://gitlab.gnome.org/Infrastructure/pika-macos-build)
|
||||
which is how we build PIKA for macOS.
|
||||
|
||||
We also know that PIKA is built on various \*BSD, proprietary Unixes,
|
||||
even on GNU-Hurd and less known systems such as Haiku OS but we don't
|
||||
have much details to help you there. Yet we still welcome patches to
|
||||
improve situation on any platform.
|
||||
|
||||
In any case, if you use a system providing too old packages, you might
|
||||
be forced to build from source (tarballs or repositories) the various
|
||||
dependencies list in `INSTALL`.
|
||||
|
||||
## Additional Requirements
|
||||
|
||||
Our autotools build system requires the following packages (or newer
|
||||
versions) installed when building from git (unlike building from
|
||||
tarball):
|
||||
|
||||
* GNU autoconf 2.54 or over
|
||||
- ftp://ftp.gnu.org/gnu/autoconf/
|
||||
* GNU automake 1.13 or over
|
||||
- ftp://ftp.gnu.org/gnu/automake/
|
||||
* GNU libtool 1.5 or over
|
||||
- ftp://ftp.gnu.org/gnu/libtool/
|
||||
|
||||
Alternatively a build with meson 0.53.0 or over is possible but it is
|
||||
not complete yet, hence not usable for packaging (yet usable for
|
||||
development).
|
||||
|
||||
For some specific build rules, you will also need:
|
||||
|
||||
* xsltproc
|
||||
- ftp://ftp.gnome.org/pub/GNOME/sources/libxslt/1.1/
|
||||
|
||||
In any cases, you will require this tool for dependency retrieval:
|
||||
|
||||
* pkg-config 0.16.0 (or preferably a newer version)
|
||||
- https://www.freedesktop.org/software/pkgconfig/
|
||||
|
||||
These are only the additional requirements if you want to compile from
|
||||
the git repository. The file `INSTALL` lists the various libraries we
|
||||
depend on.
|
||||
|
||||
|
||||
## Additional Compilation Steps
|
||||
|
||||
If you are accessing PIKA via git, then you will need to take more
|
||||
steps to get it to compile. You can do all these steps at once by
|
||||
running:
|
||||
|
||||
pika/trunk$ ./autogen.sh
|
||||
|
||||
Basically this does the following for you:
|
||||
|
||||
pika/trunk$ aclocal-1.9; libtoolize; automake-1.9 -a;
|
||||
pika/trunk$ autoconf;
|
||||
|
||||
The above commands create the "configure" script. Now you can run the
|
||||
configure script in pika/trunk to create all the Makefiles.
|
||||
|
||||
Before running autogen.sh or configure, make sure you have libtool in
|
||||
your path. Also make sure glib-2.0.m4 glib-gettext.m4, gtk-3.0.m4 and
|
||||
pkg.m4 are either installed in the same $prefix/share/aclocal relative to your
|
||||
automake/aclocal installation or call autogen.sh as follows:
|
||||
|
||||
$ ACLOCAL_FLAGS="-I $prefix/share/aclocal" ./autogen.sh
|
||||
|
||||
Note that autogen.sh runs configure for you. If you wish to pass
|
||||
options like --prefix=/usr to configure you can give those options to
|
||||
autogen.sh and they will be passed on to configure.
|
||||
|
||||
If AUTOGEN_CONFIGURE_ARGS is set, these options will also be passed to
|
||||
the configure script. If for example you want to enable the build of
|
||||
the PIKA API reference manuals, you can set AUTOGEN_CONFIGURE_ARGS to
|
||||
"--enable-gi-docgen".
|
||||
|
||||
If you want to use libraries from a non-standard prefix, you should set
|
||||
PKG_CONFIG_PATH appropriately. Some libraries do not use pkgconfig, see
|
||||
the output of ./configure --help for information on what environment
|
||||
variables to set to point the compiler and linker to the correct path.
|
||||
Note that you need to do this even if you are installing PIKA itself
|
||||
into the same prefix as the library.
|
||||
|
||||
|
||||
## Patches
|
||||
|
||||
The best way to submit patches is to provide files created with
|
||||
git-format-patch. The recommended command for a patch against the
|
||||
`master` branch is:
|
||||
|
||||
$ git format-patch origin/master
|
||||
|
||||
It is recommended that you file a bug report in our
|
||||
[tracker](https://gitlab.gnome.org/GNOME/pika) and either create a merge
|
||||
request or attach your patch to the report as a plain text file, not
|
||||
compressed.
|
||||
|
||||
Please follow the guidelines for coding style and other requirements
|
||||
listed in [CODING_STYLE.md](https://developer.pika.org/core/coding_style/). When
|
||||
you will contribute your first patches, you will notice that we care very much
|
||||
about clean and tidy code, which helps for understanding. Hence we care about
|
||||
coding style and consistency!
|
||||
|
||||
|
||||
## Auto-generated Files
|
||||
|
||||
Please notice that some files in the source are generated from other
|
||||
sources. All those files have a short notice about being generated
|
||||
somewhere at the top. Among them are the files ending in `pdb.[ch]` in
|
||||
the `libpika/` directory and the files ending in `cmds.c` in the
|
||||
`app/pdb/` subdirectory. Those are generated from the respective `.pdb`
|
||||
files in `pdb/groups`.
|
||||
|
||||
Other files are:
|
||||
|
||||
* `plug-ins/common/Makefile.am` generated by running
|
||||
`plug-ins/common/mkgen.pl`.
|
||||
* `icons/Color/Makefile.am` and `icons/Symbolic/Makefile.am` generated
|
||||
by `tools/generate-icon-makefiles.py`
|
||||
* `AUTHORS` from `authors.xml`
|
23
devel-docs/PIKA3-API-Changes.txt
Normal file
@ -0,0 +1,23 @@
|
||||
This file contains a list of changes that can/must be done when
|
||||
we break API/ABI for 3.x.
|
||||
|
||||
|
||||
- Move PIKA_REPEAT_TRUNCATE to the start of the enum and rename it
|
||||
to NONE. Rename the current NONE to EXTEND or something.
|
||||
|
||||
- Add LOTS of padding to all public class structs.
|
||||
|
||||
- Have private pointers in all public instance structs, not just
|
||||
GET_PRIVATE() macros, in order to inspect the private structs
|
||||
easily in the debugger.
|
||||
|
||||
- Remove compat values from all enums.
|
||||
|
||||
- Add user_data to all functions passed to pika_widgets_init()
|
||||
|
||||
- Preferably make pika_widgets_init() take a vtable with padding.
|
||||
|
||||
- Change pika_prop_foo_new() to use the nick as label, or find some
|
||||
other way to use the nick.
|
||||
|
||||
- Pass the plug-in protocol version on the plug-in command line.
|
272
devel-docs/PIKA3-plug-in-porting-guide/API-for-resources.md
Normal file
@ -0,0 +1,272 @@
|
||||
# API changes in libpika and the PDB for resources
|
||||
|
||||
This explains changes to the PIKA API from v2 to v3,
|
||||
concerning resources.
|
||||
|
||||
The audience is plugin authors, and PIKA developers.
|
||||
|
||||
### Resources
|
||||
|
||||
A resource is a chunk of data that can be installed with PIKA
|
||||
and is used by painting tools or for other rendering tasks.
|
||||
Usually known as brush, font, palette, pattern, gradient and so forth.
|
||||
|
||||
### Resources are now first class objects
|
||||
|
||||
PikaResource is now a class in libpika.
|
||||
|
||||
It has subclasses:
|
||||
|
||||
- Brush
|
||||
- Font
|
||||
- Gradient
|
||||
- Palette
|
||||
- Pattern
|
||||
|
||||
Formerly, the PIKA API had functions operating on resources by name.
|
||||
Now, there are methods on resource objects.
|
||||
Methods take an instance of the object as the first argument,
|
||||
often called "self."
|
||||
|
||||
This means that where you formerly used a string name to refer to a resource object,
|
||||
now you usually should pass an instance of an object.
|
||||
|
||||
### Changes to reference documents
|
||||
|
||||
#### libpika API reference
|
||||
|
||||
Shows classes Brush, Font, and so forth.
|
||||
The classes have instance methods taking the instance as the first argument.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
gboolean gboolean pika_brush_delete(gcharray) => gboolean pika_brush_delete ( PikaBrush*)
|
||||
```
|
||||
|
||||
The classes may also have class methods still taking string names.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
gboolean pika_brush_id_is_valid (const gchar* id)
|
||||
```
|
||||
|
||||
Is a class method (in the "Functions" section of the class) taking the ID
|
||||
(same as the name) to test whether such a brush is installed in Pika core.
|
||||
|
||||
#### PDB Browser
|
||||
|
||||
Remember the PDB Browser shows the C API. You must mentally convert
|
||||
to the API in bound languages.
|
||||
|
||||
Shows some procedures that now take type e.g. PikaBrush
|
||||
where formerly they took type gcharray i.e. strings.
|
||||
|
||||
Shows some procedures that take a string name of a brush.
|
||||
These are usually class methods.
|
||||
|
||||
#### Other changes to the API
|
||||
|
||||
Many of the Pika functions dealing with the context
|
||||
now take or return an instance of a resource.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
gcharray* pika_context_get_brush (void) => PikaBrush* pika_context_get_brush (void)
|
||||
```
|
||||
|
||||
A few functions have even more changed signature:
|
||||
|
||||
```
|
||||
gint pika_palette_get_info (gcharray) =>
|
||||
gint pika_palette_get_color_count (PikaPalette*)
|
||||
```
|
||||
|
||||
The name and description of this function are changed
|
||||
to accurately describe that the function only returns an integer
|
||||
(formerly, the description said it also returned the name of the palette.)
|
||||
|
||||
### New resource objects
|
||||
|
||||
FUTURE
|
||||
|
||||
Formerly there were no methods in the libpika API or the PDB for objects:
|
||||
|
||||
- Dynamics
|
||||
- ColorProfile
|
||||
- ToolPreset
|
||||
|
||||
These classes exist primarily so that plugins can let a user choose an instance,
|
||||
and pass the instance on to other procedures.
|
||||
|
||||
### Traits
|
||||
|
||||
Informally, resources can have these traits:
|
||||
|
||||
- Nameable
|
||||
- Creatable/Deleable
|
||||
- Cloneable (Duplicatable)
|
||||
- Editable
|
||||
|
||||
Some resource subclasses don't have all traits.
|
||||
|
||||
### ID's and names
|
||||
|
||||
The ID and name of a resource are currently the same.
|
||||
(Some documents and method names may use either word, inconsistently.)
|
||||
|
||||
You usually use resource instances instead of their IDs.
|
||||
This will insulate your code from changes to PIKA re ID versus name.
|
||||
|
||||
A plugin should not use a resource's ID.
|
||||
A plugin should not show the ID/name to a user.
|
||||
The PIKA app shows the names of resources as a convenience to users,
|
||||
but usually shows resources visually, that is, iconically.
|
||||
An ID is opaque, that is, used internally by PIKA.
|
||||
|
||||
FUTURE: the ID and name of a resource are distinct.
|
||||
Different resource instances may have the same name.
|
||||
Methods returning lists of resources or resource names may return
|
||||
lists having duplicate names.
|
||||
|
||||
### Resource instances are references to underlying data
|
||||
|
||||
A resource instance is a proxy, or reference, to the underlying data.
|
||||
Methods on the instance act on the underlying data.
|
||||
The underlying data is in PIKA's store of resources.
|
||||
|
||||
It is possible for a resource instance to be "invalid"
|
||||
that is, referring to underlying data that does not exist,
|
||||
usually when a user uninstalls the thing.
|
||||
|
||||
### Creating Resources
|
||||
|
||||
Installing a resource is distinct from creating a resource.
|
||||
|
||||
PIKA lets you create some resources.
|
||||
You can't create fonts in PIKA, you can only install them.
|
||||
For those resources that PIKA lets you create,
|
||||
the act of creating it also installs it.
|
||||
|
||||
For resources that you can create in PIKA:
|
||||
|
||||
- some you create using menu items
|
||||
- some you can create using the API
|
||||
|
||||
The API does not let you create a raster brush.
|
||||
|
||||
The API does let you create a parametric brush.
|
||||
For example, in Python:
|
||||
```
|
||||
brush = Pika.Brush.new("Foo")
|
||||
```
|
||||
creates a new parametric brush.
|
||||
|
||||
Note that the passed name is a proposed name.
|
||||
If the name is already in use,
|
||||
the new brush will have a different name.
|
||||
The brush instance will always be valid.
|
||||
|
||||
### Getting Resources by ID
|
||||
|
||||
Currently, you usually ask the user to interactively choose a resource.
|
||||
|
||||
If you must get a reference to a resource for which you know the ID,
|
||||
you can new() the resource class and set it's ID property.
|
||||
See below.
|
||||
|
||||
FUTURE Resource classes have get_by_id() methods.
|
||||
|
||||
If such a named resource is currently installed,
|
||||
get_by_id() returns a valid instance of the resource class.
|
||||
If such a named resource is not currently installed,
|
||||
the method returns an error.
|
||||
|
||||
### Uninitialized or invalid resource instances
|
||||
|
||||
You can create an instance of a resource class that is invalid.
|
||||
|
||||
For example, in Python:
|
||||
|
||||
```
|
||||
brush = Pika.Brush()
|
||||
brush.set_property("id", "Foo")
|
||||
```
|
||||
creates an instance that is invalid because there is no underlying data in the PIKA store
|
||||
(assuming a brush named "Foo" is not installed.)
|
||||
|
||||
Ordinarily, you would not use such a construct.
|
||||
Instead, you should use the new() method
|
||||
(for resource classes where it is defined)
|
||||
which creates, installs, and returns a valid instance except in dire circumstances (out of memory.)
|
||||
|
||||
### Invalid resource instances due to uninstalls
|
||||
|
||||
A plugin may have a resource as a parameter.
|
||||
|
||||
An interactive plugin may show a chooser widget to let a user choose a resource.
|
||||
The user's choices may be saved in settings.
|
||||
|
||||
In the same sesssion of PIKA, or in a subsequent session,
|
||||
a user may invoke the plugin again.
|
||||
Then the saved settings are displayed in the plugin's dialog
|
||||
(when the second invocation is also interactive).
|
||||
|
||||
When, in the meantime (between invocations of the plugin)
|
||||
a user has uninstalled the reference resource,
|
||||
the resource, as a reference, is invalid.
|
||||
A well-written plugin should handle this case.
|
||||
|
||||
Resource classes have:
|
||||
|
||||
- is_valid() instance method
|
||||
- id_is_valid(char * name) class method
|
||||
|
||||
Well-written plugins should use these methods to ensure
|
||||
that saved (deserialized) resource instances
|
||||
are valid before subsequently using them.
|
||||
|
||||
|
||||
### Naming and renaming
|
||||
|
||||
As mentioned above, currently names must be unique.
|
||||
|
||||
For some resources, the method rename(char * name) changes the name.
|
||||
The method fails if the new name is already used.
|
||||
|
||||
When the instance is invalid to start with
|
||||
(it has an ID that does not refer to any installed data)
|
||||
renaming it can succeed and then it creates a valid instance.
|
||||
|
||||
### Duplicating
|
||||
|
||||
Duplicating a resource creates and installs the underlying data,
|
||||
under a new, generated name.
|
||||
|
||||
The duplicate() method on an instance returns a new instance.
|
||||
|
||||
### Deleting
|
||||
|
||||
You can delete some resources. This uninstalls them.
|
||||
You can delete some brushes, palettes, and gradients,
|
||||
when they are writeable i.e. editable,
|
||||
which usually means that a user previously created them.
|
||||
You can't delete fonts and patterns.
|
||||
|
||||
You can delete using the delete() instance method
|
||||
|
||||
When you delete a resource, the instance (the proxy in a variable) continues to exist, but is invalid.
|
||||
|
||||
### Resource lists
|
||||
|
||||
Some functions in PIKA return lists of resource names,
|
||||
representing the set of resources installed.
|
||||
|
||||
For example: pika_brushes_get_list.
|
||||
|
||||
This returns a list of strings, the ID's of the resources.
|
||||
The list will have no duplicates.
|
||||
|
||||
FUTURE: this will return a list of resource instances, and their names may have duplicates.
|
15
devel-docs/PIKA3-plug-in-porting-guide/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
Here you'll find documentation useful for porting older PIKA
|
||||
plug-ins, especially Python ones, to the PIKA 3.0 APIs.
|
||||
|
||||
Files:
|
||||
|
||||
- [classes.md:](classes.md)
|
||||
A list of some of the important classes and modules in PIKA 3.0.
|
||||
|
||||
- [pdb-calls.md:](pdb-calls.md)
|
||||
An incomplete list of old PDB functions and their equivalents,
|
||||
using Python classes.
|
||||
|
||||
- [removed_functions.md:](removed_functions.md)
|
||||
Functions that have been removed from PIKA, and their replacements.
|
||||
|
100
devel-docs/PIKA3-plug-in-porting-guide/classes.md
Normal file
@ -0,0 +1,100 @@
|
||||
# Useful Modules/Classes in PIKA 3.0+
|
||||
|
||||
Here's a guide to the modules you're likely to need.
|
||||
It's a work in progress: feel free to add to it.
|
||||
|
||||
Eventually we'll have online documentation for these classes.
|
||||
In the meantime, you can generate your own:
|
||||
```
|
||||
HTMLDOCDIR=/path/to/doc/dir
|
||||
g-ir-doc-tool -I /path/to/share/gir-1.0/ --language=Python -o $HTMLDOCDIR Gimp-3.0.gir
|
||||
```
|
||||
Then browse $HTMLDOCDIR with yelp, or generate HTML from it:
|
||||
```
|
||||
cd $HTMLDOCDIR
|
||||
yelp-build cache *.page
|
||||
yelp-build html .
|
||||
|
||||
```
|
||||
|
||||
You can also get some information in PIKA's Python console with
|
||||
*help(module)* or *help(object)*, and you can get a list of functions
|
||||
with *dir(object)*.
|
||||
|
||||
## Gimp
|
||||
|
||||
The base module: almost everything is under Pika.
|
||||
|
||||
## Pika.Image
|
||||
|
||||
The image object.
|
||||
|
||||
Some operations that used to be PDB calls, like
|
||||
```
|
||||
pdb.pika_selection_layer_alpha(layer)
|
||||
```
|
||||
are now in the Image object, e.g.
|
||||
```
|
||||
img.select_item(Pika.ChannelOps.REPLACE, layer)
|
||||
```
|
||||
|
||||
## Pika.Layer
|
||||
|
||||
The layer object.
|
||||
|
||||
```
|
||||
fog = Pika.Layer.new(image, name,
|
||||
drawable.width(), drawable.height(), type, opacity,
|
||||
Pika.LayerMode.NORMAL)
|
||||
```
|
||||
|
||||
## Pika.Selection
|
||||
|
||||
Selection operations that used to be in the PDB, e.g.
|
||||
```
|
||||
pdb.pika_selection_none(img)
|
||||
```
|
||||
are now in the Pika.Selection module, e.g.
|
||||
```
|
||||
Pika.Selection.none(img)
|
||||
```
|
||||
|
||||
## Pika.ImageType
|
||||
|
||||
A home for image types like RGBA, GRAY, etc:
|
||||
```
|
||||
Pika.ImageType.RGBA_IMAGE
|
||||
```
|
||||
|
||||
## Pika.FillType
|
||||
|
||||
e.g. Pika.FillType.TRANSPARENT, Pika.FillType.BACKGROUND
|
||||
|
||||
## Pika.ChannelOps
|
||||
|
||||
The old channel op definitions in the pikafu module, like
|
||||
```
|
||||
CHANNEL_OP_REPLACE
|
||||
```
|
||||
are now in their own module:
|
||||
|
||||
```
|
||||
Pika.ChannelOps.REPLACE
|
||||
```
|
||||
|
||||
## Pika.RGB
|
||||
|
||||
In legacy plug-ins you could pass a simple list of integers, like (0, 0, 0).
|
||||
In 3.0+, create a Pika.RGB object:
|
||||
|
||||
```
|
||||
c = Pika.RGB()
|
||||
c.set(240.0, 180.0, 70.0)
|
||||
```
|
||||
or
|
||||
```
|
||||
c.r = 0
|
||||
c.g = 0
|
||||
c.b = 0
|
||||
c.a = 1
|
||||
```
|
76
devel-docs/PIKA3-plug-in-porting-guide/pdb-calls.md
Normal file
@ -0,0 +1,76 @@
|
||||
# PDB equivalence
|
||||
|
||||
A table of old PDB calls, and their equivalents in the PIKA 3.0+ world.
|
||||
|
||||
This document is a work in progress. Feel free to add to it.
|
||||
|
||||
## Undo/Context
|
||||
|
||||
| Removed function | Replacement |
|
||||
| -------------------------------- | ----------------------------
|
||||
| pika_undo_push_group_start | image.undo_group_start() |
|
||||
| pika_undo_push_group_end | image.undo_group_end() |
|
||||
| pika.context_push() | Pika.context_push() |
|
||||
| pika.context_push() | Pika.context_push() |
|
||||
| pika_context_get_background | Pika.context_get_background
|
||||
| pika_context_set_background | Pika.context_set_background
|
||||
|
||||
## File load/save
|
||||
|
||||
| Removed function | Replacement |
|
||||
| -------------------------------- | ----------------------------
|
||||
| pika_file_load | Pika.file_load |
|
||||
| pika_file_save | Pika.file_save |
|
||||
|
||||
## Selection operations
|
||||
|
||||
Selection operations are now in the Pika.Selection class (except
|
||||
a few in the Image class). E.g.
|
||||
|
||||
| Removed function | Replacement |
|
||||
| -------------------------------- | ----------------------------
|
||||
| pdb.pika_selection_invert(img) | Pika.Selection.invert(img) |
|
||||
| pdb.pika_selection_none(img) | Pika.Selection.none(img) |
|
||||
| pdb.pika_selection_layer_alpha(layer) | img.select_item(Pika.ChannelOps.REPLACE, layer) |
|
||||
| pika_image_select_item | img.select_item(channel_op, layer) |
|
||||
|
||||
## Filling and Masks
|
||||
|
||||
| Removed function | Replacement |
|
||||
| -------------------------------- | ----------------------------
|
||||
| Pika.drawable_fill() | layer.fill() |
|
||||
| pdb.pika_edit_fill(FILL_BACKGROUND) | layer.edit_fill(Pika.FillType.BACKGROUND) |
|
||||
| pika_layer_add_mask | layer.add_mask
|
||||
| pika_layer_remove_mask | layer.remove_mask
|
||||
|
||||
## Miscellaneous and Non-PDB Calls
|
||||
|
||||
| Removed function | Replacement |
|
||||
| -------------------------------- | ----------------------------
|
||||
| pika_displays_flush | Pika.displays_flush
|
||||
| pika_image_insert_layer | image.insert_layer
|
||||
|
||||
|
||||
## Plug-ins
|
||||
|
||||
Calling other plug-ins is trickier than before. The old
|
||||
```
|
||||
pdb.script_fu_drop_shadow(img, layer, -3, -3, blur,
|
||||
(0, 0, 0), 80.0, False)
|
||||
```
|
||||
becomes
|
||||
```
|
||||
c = Pika.RGB()
|
||||
c.set(240.0, 180.0, 70.0)
|
||||
Pika.get_pdb().run_procedure('script-fu-drop-shadow',
|
||||
[ Pika.RunMode.NONINTERACTIVE,
|
||||
GObject.Value(Pika.Image, img),
|
||||
GObject.Value(Pika.Drawable, layer),
|
||||
GObject.Value(GObject.TYPE_DOUBLE, -3),
|
||||
GObject.Value(GObject.TYPE_DOUBLE, -3),
|
||||
GObject.Value(GObject.TYPE_DOUBLE,blur),
|
||||
c,
|
||||
GObject.Value(GObject.TYPE_DOUBLE, 80.0),
|
||||
GObject.Value(GObject.TYPE_BOOLEAN, False)
|
||||
])
|
||||
```
|
@ -0,0 +1,175 @@
|
||||
|
||||
|
||||
## About this document
|
||||
|
||||
This describes *some* changes needed to port a Scriptfu script to PIKA 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 PIKA 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 | PikaDrawable | gint, PikaObjectArray | int (an ID) | int (a length) vector |
|
||||
| Pass obj array | gint, PikaInt32Array | gint, PikaObjectArray | int vector | int vector |
|
||||
| Recv obj array | gint, PikaInt32Array | gint, PikaObjectArray | int vector | int vector |
|
||||
| Pass set of str | gint, PikaStringArray | GStrv | int list | list |
|
||||
| Recv set of str | gint, PikaStringArray | GStrv | int list | list |
|
||||
|
||||
(Where "obj" means an object of a PIKA type such as PikaDrawable 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:
|
||||
|
||||
(pika-file-load RUN-NONINTERACTIVE "/tmp/foo" "")
|
||||
=> (pika-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 PikaDrawable,
|
||||
but now they take an array of PikaDrawable ( type PikaObjectArray.)
|
||||
(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:
|
||||
|
||||
(pika-edit-copy drawable) => (pika-edit-copy 1 (vector drawable))
|
||||
|
||||
(pika-edit-copy 2) => (pika-edit-copy 1 '#(2))
|
||||
|
||||
### The PDB procedures which formerly took single Drawable and now take PikaObjectArray
|
||||
|
||||
- Many of the file load/save procedures.
|
||||
- pika-color-picker
|
||||
- pika-edit-copy
|
||||
- pika-edit-cut
|
||||
- pika-edit-named-copy
|
||||
- pika-edit-named-cut
|
||||
- pika-file-save
|
||||
- pika-image-pick-color
|
||||
- pika-selection-float
|
||||
- pika-xcf-save
|
||||
|
||||
|
||||
### Receiving an array of drawables
|
||||
|
||||
Formerly a PDB procedure returning an array of drawables (or other PIKA objects)
|
||||
had a signature specifying a returned gint and PikaInt32Array.
|
||||
Now the signature specifies a returned gint and PikaObjectArray.
|
||||
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:
|
||||
|
||||
(pika-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,
|
||||
|
||||
(pika-image-get-layers (car (pika-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-save.
|
||||
|
||||
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 (pika-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 PIKA 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 PIKA developers.
|
222
devel-docs/PIKA3-plug-in-porting-guide/removed_functions.md
Normal file
@ -0,0 +1,222 @@
|
||||
## Removed Functions
|
||||
|
||||
These functions have been removed from PIKA 3. Most of them were deprecated
|
||||
since PIKA 2.10.x or older versions. As we bump the major version, it is time
|
||||
to start with a clean slate.
|
||||
|
||||
Below is a correspondence table with replacement function. The replacement is
|
||||
not necessarily a direct search-and-replace equivalent. Some may have different
|
||||
parameters, and in some case, it may require to think a bit about how things
|
||||
work to reproduce the same functionality. Nevertheless everything which was
|
||||
possible in the previous API is obviously still possible.
|
||||
|
||||
| Removed function | Replacement |
|
||||
| ----------------------------------------------- | ------------------------------------------------- |
|
||||
| `pika_attach_new_parasite()` | `pika_attach_parasite()` |
|
||||
| `pika_brightness_contrast()` | `pika_drawable_brightness_contrast()` |
|
||||
| `pika_brushes_get_brush()` | `pika_context_get_brush()` |
|
||||
| `pika_brushes_get_brush_data()` | `pika_brush_get_pixels()` |
|
||||
| `pika_brushes_get_spacing()` | `pika_brush_get_spacing()` |
|
||||
| `pika_brushes_set_spacing()` | `pika_brush_set_spacing()` |
|
||||
| `pika_by_color_select()` | `pika_image_select_color()` |
|
||||
| `pika_by_color_select_full()` | `pika_image_select_color()` |
|
||||
| `pika_channel_menu_new()` | `pika_channel_combo_box_new()` |
|
||||
| `pika_checks_get_shades()` | `pika_checks_get_colors()` |
|
||||
| `pika_color_balance()` | `pika_drawable_color_color_balance()` |
|
||||
| `pika_color_display_convert()` | `pika_color_display_convert_buffer()` |
|
||||
| `pika_color_display_convert_surface()` | `pika_color_display_convert_buffer()` |
|
||||
| `pika_color_display_stack_convert()` | `pika_color_display_stack_convert_buffer()` |
|
||||
| `pika_color_display_stack_convert_surface()` | `pika_color_display_stack_convert_buffer()` |
|
||||
| `pika_color_profile_combo_box_add()` | `pika_color_profile_combo_box_add_file()` |
|
||||
| `pika_color_profile_combo_box_get_active()` | `pika_color_profile_combo_box_get_active_file()` |
|
||||
| `pika_color_profile_combo_box_set_active()` | `pika_color_profile_combo_box_set_active_file()` |
|
||||
| `pika_color_profile_store_add()` | `pika_color_profile_store_add_file()` |
|
||||
| `pika_colorize()` | `pika_drawable_colorize_hsl()` |
|
||||
| `pika_context_get_transform_recursion()` | *N/A* |
|
||||
| `pika_context_set_transform_recursion()` | *N/A* |
|
||||
| `pika_curves_explicit()` | `pika_drawable_curves_explicit()` |
|
||||
| `pika_curves_spline()` | `pika_drawable_curves_spline()` |
|
||||
| `pika_desaturate()` | `pika_drawable_desaturate()` |
|
||||
| `pika_desaturate_full()` | `pika_drawable_desaturate()` |
|
||||
| `pika_drawable_attach_new_parasite()` | `pika_item_attach_parasite()` |
|
||||
| `pika_drawable_bpp()` | `pika_drawable_get_bpp()` |
|
||||
| `pika_drawable_delete()` | `pika_item_delete()` |
|
||||
| `pika_drawable_get_image()` | `pika_item_get_image()` |
|
||||
| `pika_drawable_get_linked()` | *N/A* |
|
||||
| `pika_drawable_get_name()` | `pika_item_get_name()` |
|
||||
| `pika_drawable_get_tattoo()` | `pika_item_get_tattoo()` |
|
||||
| `pika_drawable_get_visible()` | `pika_item_get_visible()` |
|
||||
| `pika_drawable_height()` | `pika_drawable_get_height()` |
|
||||
| `pika_drawable_is_channel()` | `pika_item_is_channel()` |
|
||||
| `pika_drawable_is_layer()` | `pika_item_is_layer()` |
|
||||
| `pika_drawable_is_layer_mask()` | `pika_item_is_layer_mask()` |
|
||||
| `pika_drawable_is_text_layer()` | `pika_item_is_text_layer()` |
|
||||
| `pika_drawable_is_valid()` | `pika_item_is_valid()` |
|
||||
| `pika_drawable_menu_new()` | `pika_drawable_combo_box_new()` |
|
||||
| `pika_drawable_offsets()` | `pika_drawable_get_offsets()` |
|
||||
| `pika_drawable_parasite_attach()` | `pika_item_attach_parasite()` |
|
||||
| `pika_drawable_parasite_detach()` | `pika_item_detach_parasite()` |
|
||||
| `pika_drawable_parasite_find()` | `pika_item_get_parasite()` |
|
||||
| `pika_drawable_parasite_list()` | `pika_item_get_parasite_list()` |
|
||||
| `pika_drawable_preview_new()` | `pika_drawable_preview_new_from_drawable()` |
|
||||
| `pika_drawable_preview_new_from_drawable_id()` | `pika_drawable_preview_new_from_drawable()` |
|
||||
| `pika_drawable_set_image()` | *N/A* |
|
||||
| `pika_drawable_set_linked()` | *N/A* |
|
||||
| `pika_drawable_set_name()` | `pika_item_set_name()` |
|
||||
| `pika_drawable_set_tattoo()` | `pika_item_set_tattoo()` |
|
||||
| `pika_drawable_set_visible()` | `pika_item_set_visible()` |
|
||||
| `pika_drawable_transform_2d()` | `pika_item_transform_2d()` |
|
||||
| `pika_drawable_transform_2d_default()` | `pika_item_transform_2d()` |
|
||||
| `pika_drawable_transform_flip()` | `pika_item_transform_flip()` |
|
||||
| `pika_drawable_transform_flip_default()` | `pika_item_transform_flip()` |
|
||||
| `pika_drawable_transform_flip_simple()` | `pika_item_transform_flip_simple()` |
|
||||
| `pika_drawable_transform_matrix()` | `pika_item_transform_matrix()` |
|
||||
| `pika_drawable_transform_matrix_default()` | `pika_item_transform_matrix()` |
|
||||
| `pika_drawable_transform_perspective()` | `pika_item_transform_perspective()` |
|
||||
| `pika_drawable_transform_perspective_default()` | `pika_item_transform_perspective()` |
|
||||
| `pika_drawable_transform_rotate()` | `pika_item_transform_rotate()` |
|
||||
| `pika_drawable_transform_rotate_default()` | `pika_item_transform_rotate()` |
|
||||
| `pika_drawable_transform_rotate_simple()` | `pika_item_transform_rotate_simple()` |
|
||||
| `pika_drawable_transform_scale()` | `pika_item_transform_scale()` |
|
||||
| `pika_drawable_transform_scale_default()` | `pika_item_transform_scale()` |
|
||||
| `pika_drawable_transform_shear()` | `pika_item_transform_shear()` |
|
||||
| `pika_drawable_transform_shear_default()` | `pika_item_transform_shear()` |
|
||||
| `pika_drawable_width()` | `pika_drawable_get_width()` |
|
||||
| `pika_edit_blend()` | `pika_drawable_edit_gradient_fill()` |
|
||||
| `pika_edit_bucket_fill()` | `pika_drawable_edit_bucket_fill()` |
|
||||
| `pika_edit_bucket_fill_full()` | `pika_drawable_edit_bucket_fill()` |
|
||||
| `pika_edit_clear()` | `pika_drawable_edit_clear()` |
|
||||
| `pika_edit_fill()` | `pika_drawable_edit_fill()` |
|
||||
| `pika_edit_paste_as_new()` | `pika_edit_paste_as_new_image()` |
|
||||
| `pika_edit_named_paste_as_new()` | `pika_edit_named_paste_as_new_image()` |
|
||||
| `pika_edit_stroke()` | `pika_drawable_edit_stroke_selection()` |
|
||||
| `pika_edit_stroke_vectors()` | `pika_drawable_edit_stroke_item()` |
|
||||
| `pika_ellipse_select()` | `pika_image_select_ellipse()` |
|
||||
| `pika_enum_combo_box_set_stock_prefix()` | `pika_enum_combo_box_set_icon_prefix()` |
|
||||
| `pika_enum_stock_box_new()` | `pika_enum_icon_box_new()` |
|
||||
| `pika_enum_stock_box_new_with_range()` | `pika_enum_icon_box_new_with_range()` |
|
||||
| `pika_enum_stock_box_set_child_padding()` | `pika_enum_icon_box_set_child_padding()` |
|
||||
| `pika_enum_store_set_stock_prefix()` | `pika_enum_store_set_icon_prefix()` |
|
||||
| `pika_equalize()` | `pika_drawable_equalize()` |
|
||||
| `pika_flip()` | `pika_item_transform_flip_simple()` |
|
||||
| `pika_floating_sel_relax()` | *N/A* |
|
||||
| `pika_floating_sel_rigor()` | *N/A* |
|
||||
| `pika_free_select()` | `pika_image_select_polygon()` |
|
||||
| `pika_fuzzy_select()` | `pika_image_select_contiguous_color()` |
|
||||
| `pika_fuzzy_select_full()` | `pika_image_select_contiguous_color()` |
|
||||
| `pika_gamma()` | `pika_drawable_get_format()` |
|
||||
| `pika_get_icon_theme_dir()` | *N/A* |
|
||||
| `pika_get_path_by_tattoo()` | `pika_image_get_vectors_by_tattoo()` |
|
||||
| `pika_get_theme_dir()` | *N/A* |
|
||||
| `pika_gradients_get_gradient_data()` | `pika_gradient_get_uniform_samples()` |
|
||||
| `pika_gradients_sample_custom()` | `pika_gradient_get_custom_samples()` |
|
||||
| `pika_gradients_sample_uniform()` | `pika_gradient_get_uniform_samples()` |
|
||||
| `pika_histogram()` | `pika_drawable_histogram()` |
|
||||
| `pika_hue_saturation()` | `pika_drawable_hue_saturation()` |
|
||||
| `pika_image_add_channel()` | `pika_image_insert_channel()` |
|
||||
| `pika_image_add_layer()` | `pika_image_insert_layer()` |
|
||||
| `pika_image_add_vectors()` | `pika_image_insert_vectors()` |
|
||||
| `pika_image_attach_new_parasite()` | `pika_image_attach_parasite()` |
|
||||
| `pika_image_base_type()` | `pika_image_get_base_type()` |
|
||||
| `pika_image_free_shadow()` | `pika_drawable_free_shadow()` |
|
||||
| `pika_image_get_channel_position()` | `pika_image_get_item_position()` |
|
||||
| `pika_image_get_cmap()` | `pika_image_get_colormap()` |
|
||||
| `pika_image_get_layer_position()` | `pika_image_get_item_position()` |
|
||||
| `pika_image_get_vectors_position()` | `pika_image_get_item_position()` |
|
||||
| `pika_image_height()` | `pika_image_get_height()` |
|
||||
| `pika_image_lower_channel()` | `pika_image_lower_item()` |
|
||||
| `pika_image_lower_layer()` | `pika_image_lower_item()` |
|
||||
| `pika_image_lower_layer_to_bottom()` | `pika_image_lower_item_to_bottom()` |
|
||||
| `pika_image_lower_vectors()` | `pika_image_lower_item()` |
|
||||
| `pika_image_lower_vectors_to_bottom()` | `pika_image_lower_item_to_bottom()` |
|
||||
| `pika_image_menu_new()` | `pika_image_combo_box_new()` |
|
||||
| `pika_image_parasite_attach()` | `pika_image_attach_parasite()` |
|
||||
| `pika_image_parasite_detach()` | `pika_image_detach_parasite()` |
|
||||
| `pika_image_parasite_find()` | `pika_image_get_parasite()` |
|
||||
| `pika_image_parasite_list()` | `pika_image_get_parasite_list()` |
|
||||
| `pika_image_raise_channel()` | `pika_image_raise_item()` |
|
||||
| `pika_image_raise_layer()` | `pika_image_raise_item()` |
|
||||
| `pika_image_raise_layer_to_top()` | `pika_image_raise_item_to_top()` |
|
||||
| `pika_image_raise_vectors()` | `pika_image_raise_item()` |
|
||||
| `pika_image_raise_vectors_to_top()` | `pika_image_raise_item_to_top()` |
|
||||
| `pika_image_scale_full()` | `pika_image_scale()` |
|
||||
| `pika_image_set_cmap()` | `pika_image_set_colormap()` |
|
||||
| `pika_image_width()` | `pika_image_get_width()` |
|
||||
| `pika_install_cmap()` | *N/A* |
|
||||
| `pika_invert()` | `pika_drawable_invert()` |
|
||||
| `pika_item_get_linked()` | *N/A* |
|
||||
| `pika_item_set_linked()` | *N/A* |
|
||||
| `pika_layer_menu_new()` | `pika_layer_combo_box_new()` |
|
||||
| `pika_layer_scale_full()` | `pika_layer_scale()` |
|
||||
| `pika_layer_translate()` | `pika_item_transform_translate()` |
|
||||
| `pika_levels()` | `pika_drawable_levels()` |
|
||||
| `pika_levels_auto()` | `pika_drawable_levels_stretch()` |
|
||||
| `pika_levels_stretch()` | `pika_drawable_levels_stretch()` |
|
||||
| `pika_min_colors()` | *N/A* |
|
||||
| `pika_palettes_get_palette()` | `pika_context_get_palette()` |
|
||||
| `pika_palettes_get_palette_entry()` | `pika_palette_entry_get_color()` |
|
||||
| `pika_parasite_attach()` | `pika_attach_parasite()` |
|
||||
| `pika_parasite_data()` | `pika_parasite_get_data()` |
|
||||
| `pika_parasite_data_size()` | `pika_parasite_get_data()` |
|
||||
| `pika_parasite_detach()` | `pika_detach_parasite()` |
|
||||
| `pika_parasite_find()` | `pika_get_parasite()` |
|
||||
| `pika_parasite_flags()` | `pika_parasite_get_flags()` |
|
||||
| `pika_parasite_list()` | `pika_get_parasite_list()` |
|
||||
| `pika_parasite_name()` | `pika_parasite_get_name()` |
|
||||
| `pika_path_delete()` | `pika_image_remove_vectors()` |
|
||||
| `pika_path_get_current()` | `pika_image_get_active_vectors()` |
|
||||
| `pika_path_get_locked()` | *N/A* |
|
||||
| `pika_path_get_points()` | `pika_vectors_stroke_get_points()` |
|
||||
| `pika_path_get_point_at_dist()` | `pika_vectors_stroke_get_point_at_dist()` |
|
||||
| `pika_path_get_tattoo()` | `pika_item_get_tattoo()` |
|
||||
| `pika_path_import()` | `pika_vectors_import_from_file()` |
|
||||
| `pika_path_list()` | `pika_image_get_vectors()` |
|
||||
| `pika_path_set_current()` | `pika_image_set_active_vectors()` |
|
||||
| `pika_path_set_locked()` | *N/A* |
|
||||
| `pika_path_set_points()` | `pika_vectors_stroke_new_from_points()` |
|
||||
| `pika_path_set_tattoo()` | `pika_item_set_tattoo()` |
|
||||
| `pika_path_stroke_current()` | `pika_edit_stroke_vectors()` |
|
||||
| `pika_path_to_selection()` | `pika_image_select_item()` |
|
||||
| `pika_patterns_get_pattern()` | `pika_context_get_pattern()` |
|
||||
| `pika_patterns_get_pattern_data()` | `pika_pattern_get_pixels()` |
|
||||
| `pika_perspective()` | `pika_item_transform_perspective()` |
|
||||
| `pika_posterize()` | `pika_drawable_posterize()` |
|
||||
| `pika_prop_enum_stock_box_new()` | `pika_prop_enum_icon_box_new()` |
|
||||
| `pika_prop_stock_image_new()` | `pika_prop_icon_image_new()` |
|
||||
| `pika_prop_unit_menu_new()` | `pika_prop_unit_combo_box_new()` |
|
||||
| `pika_rect_select()` | `pika_image_select_rectangle()` |
|
||||
| `pika_rotate()` | `pika_item_transform_rotate()` |
|
||||
| `pika_round_rect_select()` | `pika_image_select_round_rectangle()` |
|
||||
| `pika_scale()` | `pika_item_transform_scale()` |
|
||||
| `pika_selection_combine()` | `pika_image_select_item()` |
|
||||
| `pika_selection_layer_alpha()` | `pika_image_select_item()` |
|
||||
| `pika_selection_load()` | `pika_image_select_item()` |
|
||||
| `pika_shear()` | `pika_item_transform_shear()` |
|
||||
| `pika_stock_init()` | `pika_icons_init()` |
|
||||
| `pika_text()` | `pika_text_fontname()` |
|
||||
| `pika_text_get_extents()` | `pika_text_get_extents_fontname()` |
|
||||
| `pika_text_layer_get_hinting()` | `pika_text_layer_get_hint_style()` |
|
||||
| `pika_text_layer_set_hinting()` | `pika_text_layer_set_hint_style()` |
|
||||
| `pika_threshold()` | `pika_drawable_threshold()` |
|
||||
| `pika_toggle_button_sensitive_update()` | `g_object_bind_property()` |
|
||||
| `pika_transform_2d()` | `pika_item_transform_2d()` |
|
||||
| `pika_unit_menu_update()` | `#PikaUnitComboBox` |
|
||||
| `pika_vectors_get_image()` | `pika_item_get_image()` |
|
||||
| `pika_vectors_get_linked()` | *N/A* |
|
||||
| `pika_vectors_get_name()` | `pika_item_get_name()` |
|
||||
| `pika_vectors_get_tattoo()` | `pika_item_get_tattoo()` |
|
||||
| `pika_vectors_get_visible()` | `pika_item_get_visible()` |
|
||||
| `pika_vectors_is_valid()` | `pika_item_is_valid()` |
|
||||
| `pika_vectors_parasite_attach()` | `pika_item_attach_parasite()` |
|
||||
| `pika_vectors_parasite_detach()` | `pika_item_detach_parasite()` |
|
||||
| `pika_vectors_parasite_find()` | `pika_item_get_parasite()` |
|
||||
| `pika_vectors_parasite_list()` | `pika_item_get_parasite_list()` |
|
||||
| `pika_vectors_set_linked()` | *N/A* |
|
||||
| `pika_vectors_set_name()` | `pika_item_set_name()` |
|
||||
| `pika_vectors_set_tattoo()` | `pika_item_set_tattoo()` |
|
||||
| `pika_vectors_set_visible()` | `pika_item_set_visible()` |
|
||||
| `pika_vectors_to_selection()` | `pika_image_select_item()` |
|
||||
| `pika_zoom_preview_get_drawable_id()` | `pika_zoom_preview_get_drawable()` |
|
||||
| `pika_zoom_preview_new()` | `pika_zoom_preview_new_from_drawable()` |
|
||||
| `pika_zoom_preview_new_from_drawable_id()` | `pika_zoom_preview_new_from_drawable()` |
|
||||
| `pika_zoom_preview_new_with_model()` | `pika_zoom_preview_new_with_model_from_drawable()`|
|
451
devel-docs/PIKA3-plug-in-porting-guide/script-fu-author-guide.md
Normal file
@ -0,0 +1,451 @@
|
||||
# Guide to changes to ScriptFu v3 for script authors
|
||||
|
||||
*Draft, until PIKA 3 is final. FIXME: rearrange and rename the cited documents*
|
||||
|
||||
## About
|
||||
|
||||
The audience is authors of Scriptfu plugins.
|
||||
This discusses how to edit v2 scripts so they will run in PIKA 3.
|
||||
|
||||
This is only about changes to ScriptFu proper.
|
||||
The PIKA PDB, which you can call in scripts, has also changed.
|
||||
That also may require you to edit scripts.
|
||||
|
||||
- For changes in signatures of PDB procedures,
|
||||
see devel-docs/PIKA3-plug-in-porting-guide/porting_scriptfu_scripts.md
|
||||
- For added, removed, and replaced PDB procedures,
|
||||
see devel-docs/PIKA3-plug-in-porting-guide/removed_functions.md
|
||||
|
||||
## Quickstart
|
||||
|
||||
A lucky few existing scripts may work in PIKA v3.
|
||||
|
||||
Some changes are most likely to break an existing plugin.:
|
||||
|
||||
- SF-VALUE is obsolete
|
||||
- TRUE and FALSE are obsolete
|
||||
- many PDB procedures are obsolete or renamed, or their signature changed
|
||||
|
||||
Once you edit a script for these changes, the script won't work in PIKA v2.
|
||||
|
||||
Other changes:
|
||||
|
||||
- you can install scripts like plugins in other languages
|
||||
- scripts can use the new mult-layer selection feature of PIKA
|
||||
- a script can abort with an error message
|
||||
- a script's settings are more fully saved
|
||||
|
||||
Those changes might not affect an existing plugin.
|
||||
You need only understand those changes when you want to use new features of PIKA.
|
||||
|
||||
A word of explanation: the PIKA developers understand these changes may be onerous.
|
||||
Script developers might need to maintain two different versions of their scripts.
|
||||
Some users will stick with PIKA 2 for a while and some will switch to PIKA 3.
|
||||
But PIKA 3 is a major version change with new features.
|
||||
A clean break is necessary to move forward with improvements.
|
||||
The situation is similar to the disruption caused by the move from Python 2 to 3.
|
||||
|
||||
|
||||
### SF-VALUE kind of argument is obsolete
|
||||
|
||||
The symbol SF-VALUE is obsolete.
|
||||
You can edit v2 scripts and replace that symbol.
|
||||
|
||||
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 add the other fields, e.g. the lower and upper limits.
|
||||
|
||||
A script that has been edited to replace SF-VALUE with SF-ADJUSTMENT
|
||||
will remain compatible with PIKA 2.
|
||||
|
||||
Example:
|
||||
|
||||
SF-VALUE "Font size (pixels)" "50"
|
||||
=>
|
||||
SF-ADJUSTMENT "Font size (pixels)" '(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 is more user-friendly.
|
||||
|
||||
### FALSE and TRUE symbols obsolete
|
||||
|
||||
FALSE and TRUE symbols are no longer defined symbols in the ScriptFu language.
|
||||
They never were in the Scheme language.
|
||||
Instead, the Scheme language has symbols #f and #t.
|
||||
|
||||
In ScriptFu v2, FALSE was equivalent to 0
|
||||
and TRUE was equivalent to 1.
|
||||
But FALSE was not equivalent to #f.
|
||||
|
||||
Formerly, you could use the = operator to compare to FALSE and TRUE.
|
||||
The = operator in Scheme is a numeric operator, not a logical operator.
|
||||
Now you can use the eq? or eqv? operators.
|
||||
|
||||
In Scheme, all values are truthy except for #f.
|
||||
The empty list is truthy.
|
||||
The numeric 0 is truthy.
|
||||
Only #f is not truthy.
|
||||
|
||||
A PDB procedure returning a single Boolean (a predicate)
|
||||
returns a list containing one element, for example (#f) or (#t).
|
||||
|
||||
#### Rationale
|
||||
|
||||
The ScriptFu language is simpler and smaller; TRUE and FALSE duplicated concepts already in the Scheme language.
|
||||
|
||||
#### Example changes
|
||||
|
||||
Registering a script:
|
||||
|
||||
SF-TOGGLE "Gradient reverse" FALSE
|
||||
=>
|
||||
SF-TOGGLE "Gradient reverse" #f
|
||||
|
||||
Calling a PDB procedure taking a boolean:
|
||||
|
||||
(pika-context-set-feather TRUE)
|
||||
=>
|
||||
(pika-context-set-feather #t)
|
||||
|
||||
Logically examining a variable for truth:
|
||||
|
||||
(if (= shadow TRUE) ...
|
||||
=>
|
||||
(if shadow ...
|
||||
|
||||
### In scripts, calls to PDB procedures that return boolean yield (#t) or (#f)
|
||||
|
||||
In ScriptFu v2, PDB procedures returning a boolean returned 1 or 0 to a script,
|
||||
that is, numeric values.
|
||||
Those were equal to the old TRUE and FALSE values.
|
||||
|
||||
Remember that a call to the PDB returns a list to the script.
|
||||
So in ScriptFu v3,
|
||||
a PDB procedure that returns a single boolean (a predicate function)
|
||||
returns (#t) or (#f), a list containing one boolean element.
|
||||
|
||||
#### Rationale
|
||||
|
||||
#t and #f are more precise representations of boolean values.
|
||||
0 and 1 are binary, but not strictly boolean.
|
||||
|
||||
The ScriptFu language is smaller if concepts of truth are not duplicated.
|
||||
|
||||
#### Example changes
|
||||
|
||||
Calling a PDB procedure that is a predicate function:
|
||||
|
||||
(if (= FALSE (car (pika-selection-is-empty theImage))) ...
|
||||
=>
|
||||
(if (car (pika-selection-is-empty theImage)) ...
|
||||
|
||||
Here, the call to the PDB returns a list of one element.
|
||||
The "car" function returns that element.
|
||||
The "if" function evaluates that element for truthy.
|
||||
|
||||
Note that to evaluate the result of a PDB call for truth,
|
||||
you should just use as above, and not use "eq?" or "eqv?".
|
||||
Such a result is always a list, and a list is truthy,
|
||||
but not equivalent to #t.
|
||||
In the ScriptFu console:
|
||||
|
||||
>(eq? #t '())
|
||||
#f
|
||||
>(eqv? #t '())
|
||||
#f
|
||||
|
||||
### Use script-fu-script-abort to throw an error
|
||||
|
||||
The function "script-fu-script-abort" is new to ScriptFu v3.
|
||||
|
||||
It causes the interpreter to stop evaluating a script
|
||||
and yield an error of type PikaPDBStatus.
|
||||
That is, it immediately returns an error to the caller.
|
||||
It is similar to the "return" statement in other languages,
|
||||
but the Scheme language has no "return" statement.
|
||||
|
||||
The function takes an error message string.
|
||||
|
||||
When the caller is the PIKA app,
|
||||
the PIKA app will show an error dialog
|
||||
having the message string.
|
||||
|
||||
When the caller is another PDB procedure (a plugin or script)
|
||||
the caller must check the result of a call to the PDB
|
||||
and propagate the error.
|
||||
ScriptFu itself always checks the result of a call to the PDB
|
||||
and propagates the error,
|
||||
concatenating error message strings.
|
||||
|
||||
The function can be used anywhere in a script,
|
||||
like you would a "return" statement in other languages.
|
||||
|
||||
Alternatively, a script can yield #f to yield a PDB error.
|
||||
See below.
|
||||
|
||||
#### Rationale
|
||||
|
||||
Formerly, scripts usually called pika-message on errors,
|
||||
without yielding an error to the caller.
|
||||
It was easy for a user to overlook the error message.
|
||||
An abort shows an error message that a user must acknowledge
|
||||
by choosing an OK button.
|
||||
|
||||
#### Example
|
||||
|
||||
This script defines a PDB procedure that aborts:
|
||||
|
||||
(define (script-fu-abort)
|
||||
(script-fu-script-abort "Too many drawables.")
|
||||
(pika-message "this never evaluated")
|
||||
)
|
||||
...
|
||||
|
||||
### A script can yield #f to throw an error
|
||||
|
||||
Here we use the word "yield" instead of the word "return".
|
||||
Neither "yield" nor "return" are reserved words in the Scheme language.
|
||||
|
||||
A Scheme text evaluates to, or yields, the value of its last expression.
|
||||
Any value other than #f, even the empty list or the list containing #f,
|
||||
is truthy.
|
||||
|
||||
A ScriptFu plugin
|
||||
(the PDB procedure that a script defines in its run func)
|
||||
whose last evaluated expression is #f
|
||||
will yield an error of type PikaPDBStatus.
|
||||
|
||||
If you don't want a ScriptFu plugin to yield an error,
|
||||
it must not evaluate to #f.
|
||||
Most existing plugins won't, since their last evaluated expression
|
||||
is usually a call to the PDB yielding a list, which is not equivalent to #f.
|
||||
|
||||
*Remember that ScriptFu does not yet let you register PDB procedures
|
||||
that return values to the caller.
|
||||
That is, you can only register a void procedure, having only side effects.
|
||||
So to yield #f does not mean to return a boolean to the caller.*
|
||||
|
||||
*Also, you can define Scheme functions internal to a script
|
||||
that yield #f but that do not signify errors.
|
||||
It is only the "run func" that defines a PDB procedure that,
|
||||
yielding #f, yields a PDB error to the caller.*
|
||||
|
||||
|
||||
#### Examples
|
||||
|
||||
(define (script-fu-always-fail)
|
||||
(begin
|
||||
; this will be evaluated and show a message in PIKA status bar
|
||||
(pika-message "Failing")
|
||||
; since last expression, is the result, and will mean error
|
||||
#f
|
||||
)
|
||||
)
|
||||
|
||||
### You can optionally install scripts like plugins in other languages
|
||||
|
||||
In v3 you can install ScriptFu scripts to a /plug-ins directory.
|
||||
You must edit the script to include a shebang in the first line:
|
||||
|
||||
#!/usr/bin/env pika-script-fu-interpreter-3.0
|
||||
|
||||
In v2 all ScriptFu scripts were usually 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/PIKA/2.99/plug-ins/myScript/myScript.scm
|
||||
|
||||
Such a script will execute in its own process.
|
||||
If it crashes, it doesn't affect PIKA or other scripts.
|
||||
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 PIKA app, and you should restart PIKA.
|
||||
|
||||
### Use script-fu-register-filter to register PDB procedures that take images
|
||||
|
||||
The function *script-fu-register-filter* is new to v3.
|
||||
It lets you declare a script that:
|
||||
|
||||
- is multi-layer capable filter, taking an image and many drawables
|
||||
- can save its settings between sessions
|
||||
|
||||
You don't specify the first two arguments "image" and "drawable"
|
||||
as you do with script-fu-register in v2.
|
||||
Those arguments are implicit.
|
||||
As a convenience, ScriptFu and PIKA 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.
|
||||
|
||||
#### Multi-layer capabilily
|
||||
|
||||
script-fu-register-filter has an argument "multilayer-capability".
|
||||
Some documents may refer to the argument as "drawable arity."
|
||||
The argument follows the "image types" argument
|
||||
and precedes the argument triples that declare formally the "other" arguments
|
||||
of your plugin.
|
||||
|
||||
Here is an abbreviated 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 types any
|
||||
SF-TWO-OR-MORE-DRAWABLE ; multi-layer capability argument
|
||||
SF-ADJUSTMENT "Radius (in pixels)" (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 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 PIKA to enable the script's menu item
|
||||
when a user has selected the appropriate count of drawables.
|
||||
|
||||
#### Settings are handled by PIKA, not ScriptFu
|
||||
|
||||
Scripts declared with script-fu-register-filter have settings that are persisted
|
||||
within and between Pika sessions. That is, the next time a user chooses the filter,
|
||||
the dialog will show the same settings as the last time they chose the filter.
|
||||
This is not true for v2 script-register-filter,
|
||||
where settings are only kept during a PIKA session.
|
||||
|
||||
The dialog for a script declared with script-fu-register-filter
|
||||
will also have buttons for resetting to initial or factory values of settings.
|
||||
|
||||
#### A script should check how many drawables were passed
|
||||
|
||||
A well-written script should throw an error if a caller does not pass the expected number of drawables, either more or fewer than declared. See below.
|
||||
|
||||
### Deprecated: using script-fu-register-filter to register PDB procedures that take images
|
||||
|
||||
Existing scripts that use script-fu-register to declare a procedure
|
||||
that takes an image and single drawable,
|
||||
are deprecated.
|
||||
They will still work and have a correct dialog in v3.
|
||||
In some future version of PIKA,
|
||||
such scripts may become obsolete.
|
||||
All newly written scripts taking an image and one or more drawables
|
||||
should use script-fu-register-filter.
|
||||
|
||||
PIKA enables the menu item for such deprecated scripts if and only if a user
|
||||
selects exactly one drawable (layer or other.)
|
||||
|
||||
### ScriptFu plugins are expected to throw errors for improper count of drawables
|
||||
|
||||
Starting with PIKA 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 obsoleted in a future version of PIKA.
|
||||
|
||||
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 calls invoked by a user, the drawable arity describes
|
||||
how many drawables the user is expected to select.
|
||||
PIKA 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 on behalf of the caller.
|
||||
|
||||
A well-written callee plugin that is passed more drawables than declared
|
||||
should return an error instead of processing any of the drawables.
|
||||
Similarly for fewer than declared.
|
||||
|
||||
A ScriptFu plugin can use script-fu-script-abort to declare an error
|
||||
when passed an improper count of drawables.
|
559
devel-docs/README.md
Normal file
@ -0,0 +1,559 @@
|
||||
---
|
||||
title: Developers documentation
|
||||
---
|
||||
|
||||
This manual holds information that you will find useful if you
|
||||
develop a PIKA plug-in or want to contribute to the PIKA core.
|
||||
|
||||
People only interested into plug-ins can probably read just the
|
||||
[Plug-in development](#plug-in-development) section. If you wish to
|
||||
contribute to all parts of PIKA, the whole documentation is of interest.
|
||||
|
||||
[TOC]
|
||||
|
||||
## Plug-in development
|
||||
### Concepts
|
||||
#### Basics
|
||||
|
||||
Plug-ins in PIKA are executables which PIKA can call upon certain
|
||||
conditions. Since they are separate executables, it means that they are
|
||||
run as their own process, making the plug-in infrastructure very robust.
|
||||
No plug-in should ever crash PIKA, even with the worst bugs. If such
|
||||
thing happens, you can consider this a core bug.
|
||||
|
||||
On the other hand, a plug-in can mess your opened files, so a badly
|
||||
developed plug-in could still leave your opened images in an undesirable
|
||||
state. If this happens, you'd be advised to close and reopen the file
|
||||
(provided you saved recently).
|
||||
|
||||
Another downside of plug-ins is that PIKA currently doesn't have any
|
||||
sandboxing ability. Since we explained that plug-ins are run by PIKA as
|
||||
independant processes, it also means they have the same rights as your
|
||||
PIKA process. Therefore be careful that you trust the source of your
|
||||
plug-ins. You should never run shady plug-ins from untrusted sources.
|
||||
|
||||
PIKA comes itself with a lot of plug-ins. Actually nearly all file
|
||||
format support is implemented as a plug-in (XCF support being the
|
||||
exception: the only format implemented as core code). This makes it a
|
||||
very good base to study plug-in development.
|
||||
|
||||
#### Procedural DataBase (PDB)
|
||||
|
||||
Obviously since plug-ins are separate processes, they need a way to
|
||||
communicate with PIKA. This is the Procedural Database role, also known
|
||||
as **PDB**.
|
||||
|
||||
The PDB is our protocol allowing plug-ins to request or send information
|
||||
from or to the main PIKA process.
|
||||
|
||||
Not only this, but every plug-in has the ability to register one or
|
||||
several procedures itself, which means that any plug-in can call
|
||||
features brought by other plug-ins through the PDB.
|
||||
|
||||
#### libpika and libpikaui
|
||||
|
||||
The PIKA project provides plug-in developers with the `libpika` library.
|
||||
This is the main library which any plug-in needs. All the core PDB
|
||||
procedures have a wrapper in `libpika` so you actually nearly never need
|
||||
to call PDB procedures explicitly (exception being when you call
|
||||
procedures registered by other plug-ins; these won't have a wrapper).
|
||||
|
||||
The `libpikaui` library is an optional one which provides various
|
||||
graphical interface utility functions, based on the PIKA toolkit
|
||||
(`GTK`). Of course, it means that linking to this library is not
|
||||
mandatory (unlike `libpika`). Some cases where you would not do this
|
||||
are: because you don't need any graphical interface (e.g. a plug-in
|
||||
doing something directly without dialog, or even a plug-in meant to be
|
||||
run on non-GUI servers); because you want to use pure GTK directly
|
||||
without going through `libpikaui` facility; because you want to make
|
||||
your GUI with another toolkit…
|
||||
|
||||
The whole C reference documentation for both these libraries can be
|
||||
generated in the main PIKA build with the `--enable-gi-docgen` autotools
|
||||
option or the `-Dgi-docgen=enabled` meson option (you need to have the
|
||||
`gi-docgen` tools installed).
|
||||
|
||||
TODO: add online links when it is up for the new APIs.
|
||||
|
||||
### Programming Languages
|
||||
|
||||
While C is our main language, and the one `libpika` and `libpikaui` are
|
||||
provided in, these 2 libraries are also introspected thanks to the
|
||||
[GObject-Introspection](https://gi.readthedocs.io/en/latest/) (**GI**)
|
||||
project. It means you can in fact create plug-ins with absolutely any
|
||||
[language with a GI binding](https://wiki.gnome.org/Projects/GObjectIntrospection/Users)
|
||||
though of course it may not always be as easy as the theory goes.
|
||||
|
||||
The PIKA project explicitly tests the following languages and even
|
||||
provides a test plug-in as a case study:
|
||||
|
||||
* [C](https://gitlab.gnome.org/GNOME/pika/-/blob/master/extensions/goat-exercises/goat-exercise-c.c) (not a binding)
|
||||
* [Python 3](https://gitlab.gnome.org/GNOME/pika/-/blob/master/extensions/goat-exercises/goat-exercise-py3.py)
|
||||
(binding)
|
||||
* [Lua](https://gitlab.gnome.org/GNOME/pika/-/blob/master/extensions/goat-exercises/goat-exercise-lua.lua)
|
||||
(binding)
|
||||
* [Vala](https://gitlab.gnome.org/GNOME/pika/-/blob/master/extensions/goat-exercises/goat-exercise-vala.vala)
|
||||
(binding)
|
||||
* [Javascript](https://gitlab.gnome.org/GNOME/pika/-/blob/master/extensions/goat-exercises/goat-exercise-gjs.js)
|
||||
(binding, not supported on Windows for the time being)
|
||||
|
||||
One of the big advantage of these automatic bindings is that they are
|
||||
full-featured since they don't require manual tweaking. Therefore any
|
||||
function in the C library should have an equivalent in any of the
|
||||
bindings.
|
||||
|
||||
TODO: binding reference documentation.
|
||||
|
||||
**Note**: several GObject-Introspection's Scheme bindings exist though
|
||||
we haven't tested them. Nevertheless, PIKA also provides historically
|
||||
the "script-fu" interface, based on an integrated Scheme implementation.
|
||||
It is different from the other bindings (even from any GI Scheme
|
||||
binding) and doesn't use `libpika`. Please see the [Script-fu
|
||||
development](#script-fu-development) section.
|
||||
|
||||
### Tutorials
|
||||
|
||||
TODO: at least in C and in one of the officially supported binding
|
||||
(ideally even in all of them).
|
||||
|
||||
### Porting from PIKA 2 plug-ins
|
||||
|
||||
### Debugging
|
||||
|
||||
PIKA provides an infrastructure to help debugging plug-ins.
|
||||
|
||||
You are invited to read the [dedicated
|
||||
documentation](debug-plug-ins.txt).
|
||||
|
||||
## Script-fu development
|
||||
|
||||
`Script-fu` is its own thing as it is a way to run Scheme script with
|
||||
PIKA. It is itself implemented as an always-running plug-in with its own
|
||||
Scheme mini-interpreter and therefore `Script-fu` scripts do not use
|
||||
`libpika` or `libpikaui`. They interface with the PDB through the
|
||||
`Script-fu` plug-in.
|
||||
|
||||
### Tutorials
|
||||
|
||||
### Porting from PIKA 2 scripts
|
||||
|
||||
## GEGL operation development
|
||||
|
||||
## Custom data
|
||||
|
||||
This section list all types of data usable to enhance PIKA
|
||||
functionalities. If you are interested to contribute default data to
|
||||
PIKA, be aware that we are looking for a very good base set, not an
|
||||
unfinite number of data for all possible usage (even the less common
|
||||
ones).
|
||||
|
||||
Furthermore we only accept data on Libre licenses:
|
||||
|
||||
* [Free Art License](https://artlibre.org/licence/lal/en/)
|
||||
* [CC0](https://creativecommons.org/publicdomain/zero/1.0/)
|
||||
* [CC BY](https://creativecommons.org/licenses/by/4.0/)
|
||||
* [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/)
|
||||
|
||||
Of course you are free to share data usable by PIKA on any license you
|
||||
want on your own. Providing them as third-party PIKA
|
||||
[extensions](#pika-extensions-gex) is probably the best idea.
|
||||
|
||||
### Brushes
|
||||
|
||||
PIKA currently supports the following brush formats:
|
||||
|
||||
* PIKA Brush (GBR): format to store pixmap brushes
|
||||
* PIKA Brush Pipe (GIH): format to store a series of pixmap brushes
|
||||
* PIKA Generated Brush (VBR): format of "generated" brushes
|
||||
* PIKA Brush Pixmap (GPB): *OBSOLETE* format to store pixel brushes
|
||||
* MyPaint brushes v1 (MYB)
|
||||
* Photoshop ABR Brush
|
||||
* Paint Shop Pro JBR Brush
|
||||
|
||||
We do fully support the PIKA formats obviously, as well as MyPaint
|
||||
brushes, since we use the official `libmypaint` library. We are not sure
|
||||
how well we support other third-party formats, especially if they had
|
||||
recent versions.
|
||||
|
||||
If you are interested in brushes from a developer perspective, you are
|
||||
welcome to read specifications of PIKA formats:
|
||||
[GBR](specifications/gbr.txt), [GIH](specifications/gih.txt),
|
||||
[VBR](specifications/vbr.txt) or the obsolete [GPB](specifications/gpb.txt).
|
||||
|
||||
If you want to contribute brushes to the official PIKA, be aware we
|
||||
would only accept brushes in non-obsolete PIKA formats. All these
|
||||
formats can be generated by PIKA itself from images.
|
||||
|
||||
If you want to contribute MyPaint brushes, we recommend to propose them
|
||||
to the [MyPaint-brushes](https://github.com/mypaint/mypaint-brushes/)
|
||||
data project, which is also used by PIKA for its default MyPaint brush
|
||||
set.
|
||||
|
||||
Otherwise, you are welcome to provide brush set in any format as
|
||||
third-party [extensions](#pika-extensions-gex).
|
||||
|
||||
### Dynamics
|
||||
|
||||
PIKA supports the PIKA Paint Dynamics format which can be generated from
|
||||
within PIKA.
|
||||
|
||||
### Patterns
|
||||
|
||||
PIKA supports the PIKA Pattern format (PAT, whose
|
||||
[specification](specifications/pat.txt) is available for developers).
|
||||
|
||||
This format can be exported by PIKA itself.
|
||||
|
||||
Alternatively PIKA supports patterns from `GdkPixbuf` (TODO: get more
|
||||
information?).
|
||||
|
||||
### Palettes
|
||||
|
||||
PIKA supports the PIKA Palette format which can be generated from within
|
||||
PIKA.
|
||||
|
||||
### Gradients
|
||||
|
||||
PIKA supports the PIKA Gradient format (GGR, whose
|
||||
[specification](specifications/ggr.txt) is available for developers)
|
||||
which can be generated from within PIKA.
|
||||
|
||||
Alternatively PIKA supports the SVG Gradient format.
|
||||
|
||||
### Themes
|
||||
|
||||
GTK3 uses CSS themes. Don't be fooled though. It's not real CSS in that
|
||||
it doesn't have all the features of real web CSS, and since it's for
|
||||
desktop applications, some things are necessarily different. What it
|
||||
means is mostly that it "looks similar" enough that people used to web
|
||||
styling should not be too disorientated.
|
||||
|
||||
You can start by looking at the [official
|
||||
documentation](https://docs.gtk.org/gtk3/migrating-themes.html) for
|
||||
theme migration (from GTK+2 to 3), which gives a good overview, though
|
||||
it's far from being perfect unfortunately.
|
||||
|
||||
Another good idea would be to look at existing well maintained GTK3
|
||||
themes to get inspiration and see how things work.
|
||||
|
||||
Finally you can look at our existing themes, like the [System
|
||||
theme](https://gitlab.gnome.org/GNOME/pika/-/blob/master/themes/System/pika.css).
|
||||
Note though that this `System` theme is pretty bare, and that's its goal
|
||||
(try to theme as few as possible over whatever is the current real
|
||||
system theme).
|
||||
|
||||
TODO: for any theme maker reading this, what we want for PIKA 3.0 are at
|
||||
least the following additional themes:
|
||||
|
||||
- a full custom theme using neutral grayscale colors with a dark and
|
||||
light variant;
|
||||
- a mid-gray neutral theme.
|
||||
|
||||
As a last trick for theme makers, we recommend to work with the
|
||||
GtkInspector tool, which allows you to test CSS rules live in the `CSS`
|
||||
tab. You can run the `GtkInspector` by going to the `File > Debug` menu
|
||||
and selecting `Start GtkInspector` menu item.
|
||||
|
||||
It also allows you to find the name of a widget to use in your CSS
|
||||
rules. To do so:
|
||||
|
||||
* Start the `GtkInspector`;
|
||||
* go on the "Objects" tab;
|
||||
* click the "target" 🞋 icon on the headerbar's top-left, then pick in
|
||||
PIKA interface the widget you are interested to style;
|
||||
* the widget name will be displayed on the top of the information area
|
||||
of the dialog.
|
||||
* Feel free to browse the various sections to see the class hierachy,
|
||||
CSS nodes and so on.
|
||||
* The second top-left button (just next to the target icon) allows you
|
||||
to switch between the details of the selected widget and the widget
|
||||
hierarchy (container widgets containing other widgets), which is also
|
||||
very useful information.
|
||||
|
||||
Additionally you can quickly switch between the light and dark variant
|
||||
of a same theme by going to "Visual" tab and switching the "Dark
|
||||
Variant" button ON or OFF.
|
||||
|
||||
### Icon themes
|
||||
|
||||
Icon sets (a.k.a. "icon themes") have been separated from themes since
|
||||
PIKA 2.10 so you can have any icon theme with any theme.
|
||||
|
||||
We currently only support 2 such icon themes — Symbolic and Color — and
|
||||
we keep around the Legacy icons.
|
||||
|
||||
We don't want too many alternative designs as official icon themes
|
||||
(people are welcome to publish their favorite designs as third-party
|
||||
icons) though we would welcome special-purpose icon themes (e.g. high
|
||||
contrast).
|
||||
|
||||
We also welcome design updates as a whole (anyone willing to work on
|
||||
this should discuss with us and propose something) and obviously fixes
|
||||
on existing icons or adding missing icons while keeping consistent
|
||||
styling.
|
||||
|
||||
See the dedicated [icons documentation](icons.md) for more technical
|
||||
information.
|
||||
|
||||
### Tool presets
|
||||
|
||||
|
||||
## PIKA extensions (*.gex*)
|
||||
|
||||
## Continuous Integration
|
||||
|
||||
For most of its continuous integration (macOS excepted), PIKA project
|
||||
uses Gitlab CI. We recommend looking the file
|
||||
[.gitlab-ci.yml](/.gitlab-ci.yml) which is the startup script.
|
||||
|
||||
The main URL for our CI system is
|
||||
[build.pika.org](https://build.pika.org) which redirects to Gitlab
|
||||
pipelines page.
|
||||
|
||||
Note that it is important to keep working CI jobs for a healthy code
|
||||
source. Therefore when you push some code which breaks the CI (you
|
||||
should receive a notification email when you do so), you are expected to
|
||||
look at the failed jobs' logs, try and understand the issue(s) and fix
|
||||
them (or ask for help). Don't just shrug this because it works locally
|
||||
(the point of the CI is to build in more conditions than developers
|
||||
usually do locally).
|
||||
|
||||
Of course, sometimes CI failures are out of our control, for instance
|
||||
when downloaded dependencies have issues, or because of runner issues.
|
||||
You should still check that these were reported and that
|
||||
packagers/maintainers of these parts are aware and working on a fix.
|
||||
|
||||
### Automatic pipelines
|
||||
|
||||
At each commit pushed to the repository, several pipelines are currently
|
||||
running, such as:
|
||||
|
||||
- Debian testing autotools and meson builds (autotools is still the
|
||||
official build system while meson is experimental).
|
||||
- Windows builds (cross or natively compiled).
|
||||
|
||||
Additionally, we test build with alternative tools or options (e.g. with
|
||||
`Clang` instead of `gcc` compiler) or jobs which may take much longer,
|
||||
such as package creation as scheduled pipelines (once every few days).
|
||||
|
||||
The above listing is not necessarily exhaustive nor is it meant to be.
|
||||
Only the [.gitlab-ci.yml](/.gitlab-ci.yml) script is meant to be
|
||||
authoritative. The top comment in this file should stay as exhaustive
|
||||
as possible.
|
||||
|
||||
### Manual pipelines
|
||||
|
||||
It is possible to trigger pipelines manually, for instance with specific
|
||||
jobs, if you have the "*Developer*" Gitlab role:
|
||||
|
||||
1. go to the [Pipelines](https://gitlab.gnome.org/GNOME/pika/-/pipelines)
|
||||
page.
|
||||
2. Hit the "*Run pipeline*" button.
|
||||
3. Choose the branch or tag you wish to build.
|
||||
4. Add relevant variables. A list of variables named `PIKA_CI_*` are
|
||||
available (just set them to any value) and will trigger specific job
|
||||
lists. These variables are listed in the top comment of
|
||||
[.gitlab-ci.yml](/.gitlab-ci.yml).
|
||||
|
||||
### Merge request pipelines
|
||||
|
||||
Special pipelines happen for merge request code. For instance, these
|
||||
also include a (non-perfect) code style check.
|
||||
|
||||
Additionally you can trigger Windows installer or flatpack standalone
|
||||
packages to be generated with the MR code as explained in
|
||||
[gitlab-mr.md](gitlab-mr.md).
|
||||
|
||||
### Release pipeline
|
||||
|
||||
Special pipelines happen when pushing git `tags`. These should be tested
|
||||
before a release to avoid unexpected release-time issues, as explained
|
||||
in [our release procedure](https://developer.pika.org/core/maintainer/release/).
|
||||
|
||||
### Exception: macOS
|
||||
|
||||
As an exception, macOS is currently built with the `Circle-CI` service.
|
||||
The whole CI scripts and documentation can be found in the dedicated
|
||||
[pika-macos-build](https://gitlab.gnome.org/Infrastructure/pika-macos-build)
|
||||
repository.
|
||||
|
||||
Eventually we want to move this pipeline to Gitlab as well.
|
||||
|
||||
## Core development
|
||||
|
||||
When writing code, any core developer is expected to follow:
|
||||
|
||||
- PIKA's [coding style](https://developer.pika.org/core/coding_style/);
|
||||
- the [directory structure](#directory-structure-of-pika-source-tree)
|
||||
- our [header file inclusion policy](includes.txt)
|
||||
|
||||
[PIKA's developer wiki](https://wiki.pika.org/index.php/Main_Page) can
|
||||
also contain various valuable resources.
|
||||
|
||||
Finally the [debugging-tips](debugging-tips.md) file contain many very
|
||||
useful tricks to help you debugging in various common cases.
|
||||
|
||||
### Newcomers
|
||||
|
||||
If this is your first time contributing to PIKA, you might be interested
|
||||
by build instructions. The previously mentioned wiki in particular has a
|
||||
[Hacking:Building](https://wiki.pika.org/wiki/Hacking:Building) page
|
||||
with various per-platform subpages. The [HACKING](HACKING.md) docs will
|
||||
also be of interest.
|
||||
|
||||
You might also like to read these [instructions on submitting
|
||||
patches](https://pika.org/bugs/howtos/submit-patch.html).
|
||||
|
||||
If you are unsure what to work on, this [list of bugs for
|
||||
newcomers](https://gitlab.gnome.org/GNOME/pika/-/issues?scope=all&state=opened&label_name[]=4.%20Newcomers)
|
||||
might be a good start. It doesn't necessarily contain only bugs for
|
||||
beginner developers. Some of them might be for experienced developers
|
||||
who just don't know yet enough the codebase.
|
||||
|
||||
Nevertheless we often recommend to rather work on topics which you
|
||||
appreciate, or even better: fixes for bugs you encounter or features you
|
||||
want. These are the most self-rewarding contributions which will really
|
||||
make you feel like developing on PIKA means developing for yourself.
|
||||
|
||||
### Core Contributors
|
||||
|
||||
### Directory structure of PIKA source tree
|
||||
|
||||
PIKA source tree can be divided into the main application, libraries, plug-ins,
|
||||
data files and some stuff that don't fit into these categories. Here are the
|
||||
top-level directories:
|
||||
|
||||
| Folder | Description |
|
||||
| --- | --- |
|
||||
| app/ | Source code of the main PIKA application |
|
||||
| app-tools/ | Source code of distributed tools |
|
||||
| build/ | Scripts for creating binary packages |
|
||||
| cursors/ | Bitmaps used to construct cursors |
|
||||
| data/ | Data files: brushes, gradients, patterns, images… |
|
||||
| desktop/ | Desktop integration files |
|
||||
| devel-docs/ | Developers documentation |
|
||||
| docs/ | Users documentation |
|
||||
| etc/ | Configuration files installed with PIKA |
|
||||
| extensions/ | Source code of extensions |
|
||||
| icons/ | Official icon themes |
|
||||
| libpika/ | Library for plug-ins (core does not link against) |
|
||||
| libpikabase/ | Basic functions shared by core and plug-ins |
|
||||
| libpikacolor/ | Color-related functions shared by core and plug-ins |
|
||||
| libpikaconfig/ | Config functions shared by core and plug-ins |
|
||||
| libpikamath/ | Mathematic operations useful for core and plug-ins |
|
||||
| libpikamodule/ | Abstracts dynamic loading of modules (used to implement loadable color selectors and display filters) |
|
||||
| libpikathumb/ | Thumbnail functions shared by core and plug-ins |
|
||||
| libpikawidgets/ | User interface elements (widgets) and utility functions shared by core and plug-ins |
|
||||
| m4macros/ | Scripts for autotools configuration |
|
||||
| menus/ | XML/XSL files used to generate menus |
|
||||
| modules/ | Color selectors and display filters loadable at run-time |
|
||||
| pdb/ | Scripts for PDB source code generation |
|
||||
| plug-ins/ | Source code for plug-ins distributed with PIKA |
|
||||
| po/ | Translations of strings used in the core application |
|
||||
| po-libpika/ | Translations of strings used in libpika |
|
||||
| po-plug-ins/ | Translations of strings used in C plug-ins |
|
||||
| po-python/ | Translations of strings used in Python plug-ins |
|
||||
| po-script-fu/ | Translations of strings used in Script-Fu scripts |
|
||||
| po-tags/ | Translations of strings used in tags |
|
||||
| po-tips/ | Translations of strings used in tips |
|
||||
| po-windows-installer/ | Translations of strings used in the Windows installer |
|
||||
| themes/ | Official themes |
|
||||
| tools/ | Source code for non-distributed PIKA-related tools |
|
||||
| .gitlab/ | Gitlab-related templates or scripts |
|
||||
|
||||
The source code of the main PIKA application is found in the `app/` directory:
|
||||
|
||||
| Folder | Description |
|
||||
| --- | --- |
|
||||
| app/actions/ | Code of actions (`PikaAction*` defined in `app/widgets/`) (depends: GTK) |
|
||||
| app/config/ | Config files handling: PikaConfig interface and PikaRc object (depends: GObject) |
|
||||
| app/core/ | Core of PIKA **core** (depends: GObject) |
|
||||
| app/dialogs/ | Dialog widgets (depends: GTK) |
|
||||
| app/display/ | Handles displays (e.g. image windows) (depends: GTK) |
|
||||
| app/file/ | File handling routines in **core** (depends: GIO) |
|
||||
| app/file-data/ | PIKA file formats (gbr, gex, gih, pat) support (depends: GIO) |
|
||||
| app/gegl/ | Wrapper code for babl and GEGL API (depends: babl, GEGL) |
|
||||
| app/gui/ | Code that puts the user interface together (depends: GTK) |
|
||||
| app/menus/ | Code for menus (depends: GTK) |
|
||||
| app/operations/ | Custom GEGL operations (depends: GEGL) |
|
||||
| app/paint/ | Paint core that provides different ways to paint strokes (depends: GEGL) |
|
||||
| app/pdb/ | Core side of the Procedural Database, exposes internal functionality |
|
||||
| app/plug-in/ | Plug-in handling in **core** |
|
||||
| app/propgui/ | Property widgets generated from config properties (depends: GTK) |
|
||||
| app/tests/ | Core unit testing framework |
|
||||
| app/text/ | Text handling in **core** |
|
||||
| app/tools/ | User interface part of the tools. Actual tool functionality is in core |
|
||||
| app/vectors/ | Vectors framework in **core** |
|
||||
| app/widgets/ | Collection of widgets used in the application GUI |
|
||||
| app/xcf/ | XCF file handling in **core** |
|
||||
|
||||
You should also check out [pika-module-dependencies.svg](pika-module-dependencies.svg).
|
||||
**TODO**: this SVG file is interesting yet very outdated. It should not
|
||||
be considered as some kind dependency rule and should be updated.
|
||||
|
||||
### Advanced concepts
|
||||
|
||||
#### XCF
|
||||
|
||||
The `XCF` format is the core image format of PIKA, which mirrors
|
||||
features made available in PIKA. More than an image format, you may
|
||||
consider it as a work or project format, as it is not made for finale
|
||||
presentation of an artwork but for the work-in-progress processus.
|
||||
|
||||
Developers are welcome to read the [specifications of XCF](specifications/xcf.txt).
|
||||
|
||||
#### Locks
|
||||
|
||||
Items in an image can be locked in various ways to prevent different
|
||||
types of edits.
|
||||
|
||||
This is further explained in [the specifications of locks](https://developer.pika.org/core/specifications/locks/).
|
||||
|
||||
#### UI Framework
|
||||
|
||||
PIKA has an evolved GUI framework, with a toolbox, dockables, menus…
|
||||
|
||||
This [document describing how the PIKA UI framework functions and how it
|
||||
is implemented](ui-framework.txt) might be of interest.
|
||||
|
||||
#### Contexts
|
||||
|
||||
PIKA uses a lot a concept of "contexts". We recommend reading more about
|
||||
[how PikaContexts are used in PIKA](contexts.txt).
|
||||
|
||||
#### Undo
|
||||
|
||||
PIKA undo system can be challenging at times. This [quick overview of
|
||||
the undo system](undo.txt) can be of interest as a first introduction.
|
||||
|
||||
#### Parasites
|
||||
|
||||
PIKA has a concept of "parasite" data which basically correspond to
|
||||
persistent or semi-persistent data which can be attached to images or
|
||||
items (layers, channels, paths) within an image. These parasites are
|
||||
saved in the XCF format.
|
||||
|
||||
Parasites can also be attached globally to the PIKA session.
|
||||
|
||||
Parasite contents is format-free and you can use any parasite name,
|
||||
nevertheless PIKA itself uses parasite so you should read the
|
||||
[descriptions of known parasites](parasites.txt).
|
||||
|
||||
#### Metadata
|
||||
|
||||
PIKA supports Exif, IPTC and XMP metadata as well as various image
|
||||
format-specific metadata. The topic is quite huge and complex, if not
|
||||
overwhelming.
|
||||
|
||||
This [old document](https://developer.pika.org/core/specifications/exif_handling/)
|
||||
might be of interest (or maybe not, it has not been recently reviewed and might
|
||||
be widely outdated; in any case, it is not a complete document at all as we
|
||||
definitely do a lot more nowadays). **TODO**: review this document and delete or
|
||||
update it depending of whether it still makes sense.
|
||||
|
||||
#### Tagging
|
||||
|
||||
Various data in PIKA can be tagged across sessions.
|
||||
|
||||
This document on [how resource tagging in PIKA works](tagging.txt) may
|
||||
be of interest.
|
28
devel-docs/c.vim
Normal file
@ -0,0 +1,28 @@
|
||||
" PIKA coding style for vim "
|
||||
|
||||
" To enable these vim rules for PIKA only, add this command to your vimrc:
|
||||
" autocmd BufNewFile,BufRead /path/to/pika/*.[ch] source /path/to/pika/devel-docs/c.vim
|
||||
"
|
||||
" Do not use `set exrc` which is a security risk for your system since vim may
|
||||
" be tricked into running shell commands by .vimrc files hidden in malicious
|
||||
" projects (`set secure` won't protect you since it is not taken into account
|
||||
" if the files are owned by you).
|
||||
|
||||
" GNU style
|
||||
setlocal cindent
|
||||
setlocal cinoptions=>4,n-2,{2,^-2,:2,=2,g0,h2,p5,t0,+2,(0,u0,w1,m1
|
||||
setlocal shiftwidth=2
|
||||
setlocal softtabstop=2
|
||||
setlocal textwidth=79
|
||||
setlocal fo-=ro fo+=cql
|
||||
|
||||
" Tabs are always inserted as spaces.
|
||||
set expandtab
|
||||
" But if there are tabs already, show them as 8 columns.
|
||||
setlocal tabstop=8
|
||||
|
||||
" Highlight in red trailing whitespaces and tabs everywhere.
|
||||
highlight TrailingWhitespace ctermbg=LightRed guibg=LightRed
|
||||
match TrailingWhitespace /\s\+$/
|
||||
highlight ForbiddenTabs ctermbg=DarkRed guibg=DarkRed
|
||||
2match ForbiddenTabs /\t/
|
89
devel-docs/contexts.txt
Normal file
@ -0,0 +1,89 @@
|
||||
contexts.txt
|
||||
============
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
This file describes how PikaContexts are used in PIKA.
|
||||
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
One important context is the so called "user context",
|
||||
pika_get_user_context(). This context keeps track on what image the
|
||||
user currently has active, for example. Dock windows have their own
|
||||
context which does not necessarily mirror the user context. A dock
|
||||
window can be set to show information for a specific image. Plug-ins
|
||||
also have their own context.
|
||||
|
||||
|
||||
Communication between contexts
|
||||
------------------------------
|
||||
|
||||
So how do the various contexts synchronize and propagate changes?
|
||||
This is most easily explained by a sequence diagram. Let's say there
|
||||
are two image windows with different images opened in PIKA. Call them
|
||||
A and B. Let's say A is currently active. When the user activates B,
|
||||
this is the sequence of events from the focus event to the layers
|
||||
dockable have been updated with the new image. To understand the
|
||||
diagram, you have to know that the dock window has connected signal
|
||||
handlers to image changes in the user context (through a dialog
|
||||
factory getter), and the layer dockable have connected a signal
|
||||
handler to image changes in the dock window context. The sequence of
|
||||
events is as follows:
|
||||
|
||||
PikaContext PikaContext PikaItemTreeView,
|
||||
PikaDisplayShell user PikaDockWindow dock window PikaLayerTreeView
|
||||
|
||||
| | | | |
|
||||
focus event | | | |
|
||||
------->| | | | |
|
||||
| pika_context_set_display() | | |
|
||||
|--------------->|----------+ | | |
|
||||
| | | | | |
|
||||
| pika_context_set_image() | | | |
|
||||
| |<---------+ | | |
|
||||
| | | | |
|
||||
| | "image-changed" | |
|
||||
| |------------->| | |
|
||||
| | | pika_context_set_image() |
|
||||
| | |------------->| |
|
||||
| | | | "image-changed" /
|
||||
| | | | set_image()
|
||||
| | | |------------>|
|
||||
| | | | |
|
||||
|
||||
In single-window mode, the dockables listen directly to the user
|
||||
context. When switching between single-window and multi-window modes,
|
||||
the dockables are updated with their new context, just as when moving
|
||||
a dockable between different dock windows and thus also different
|
||||
contexts. The sequence diagram for single-window mode is:
|
||||
|
||||
PikaContext PikaItemTreeView
|
||||
PikaDisplayShell user PikaLayerTreeView
|
||||
|
||||
| | |
|
||||
focus event | |
|
||||
------->| | |
|
||||
| pika_context_set_display() |
|
||||
|--------------->|----------+ |
|
||||
| | | |
|
||||
| pika_context_set_image() | |
|
||||
| |<---------+ |
|
||||
| | |
|
||||
| | "image-changed" /
|
||||
| | set_image()
|
||||
| |------------->|
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
| | |
|
||||
|
||||
|
||||
Parent/child relationships
|
||||
--------------------------
|
||||
|
||||
TODO
|
4
devel-docs/g-ir-docs/docs_pages_fix.sh
Normal file
@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -i 's/<\(Prefix\|Image\)/\<\1/g' "$@"
|
||||
sed -i 's/&\([a-z0-9_]\+[^a-z0-9_;]\)/\&\1/g' "$@"
|
135
devel-docs/g-ir-docs/meson.build
Normal file
@ -0,0 +1,135 @@
|
||||
foreach lang : [ 'python', 'gjs' ]
|
||||
|
||||
# XXX meson does not allow building into subdir:
|
||||
# https://github.com/mesonbuild/meson/issues/2320
|
||||
# Otherwise I could use '-o', '@OUTDIR@' into following commands if
|
||||
# the `output` was subdir-able.
|
||||
gir_docs_dir = custom_target('g-ir-docs-' + lang + '-dir',
|
||||
depends: [ libpika_gir, libpikaui_gir ],
|
||||
input: [ ],
|
||||
output: [ 'gir-' + lang + '-dirs' ],
|
||||
command: [
|
||||
'mkdir', '-p',
|
||||
'@OUTDIR@' + '/pages/' + lang + '/PikaUi-' + pika_api_version,
|
||||
'@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version,
|
||||
'@OUTDIR@' + '/html/' + lang + '/PikaUi-' + pika_api_version,
|
||||
'@OUTDIR@' + '/html/' + lang + '/Pika-' + pika_api_version
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
## Pika Module ##
|
||||
|
||||
# XXX `output` is bogus. g-ir-doc-tool produces a lot of output,
|
||||
# basically one page per public symbol, which is more than 1000 so
|
||||
# it's not usable. Since custom_target() requires an 'output', I could
|
||||
# just set one output such as 'index.page` as a trick, but since we
|
||||
# have another issue on subdir anyway (cf. above), I use some bogus
|
||||
# file instead. The fact the bogus file is not even created does not
|
||||
# even seem to be a problem for meson.
|
||||
# Moreover I realized that the targets listed by ninja are only the
|
||||
# output files (not the target name), so I basically ends up using
|
||||
# this field to create understandable names).
|
||||
gir_docs_pages = custom_target('g-ir-Pika-' + lang + '-pages',
|
||||
depends: [ gir_docs_dir, libpika_gir ],
|
||||
input: [ libpika_gir[0] ],
|
||||
output: [ 'Pika-' + lang + '-pages' ],
|
||||
command: [
|
||||
gir_doc_tool,
|
||||
'-I', prefix / 'share/gir-1.0/',
|
||||
'-I', meson.project_build_root() / 'libpika',
|
||||
'--language=' + lang,
|
||||
'-o', '@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version,
|
||||
meson.project_build_root() / '@INPUT@'
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
# This step is completely an ugly workaround for 2 tool issues. The
|
||||
# first issue is that g-ir-doc-tool generates invalid XML by not
|
||||
# transforming less-than signs into entities. So I am special-casing
|
||||
# the one API documentation where we need to write a less-than (it will
|
||||
# need to be updated if this happens again).
|
||||
# See PIKA issue #7685.
|
||||
# The second issue is in meson itself which transforms backslash into
|
||||
# slashes preventing to write most basic regexp in a 'command'. For
|
||||
# this reason, I need to add the sed command as an external script.
|
||||
# See meson issue #1564.
|
||||
docs_pages_fix_sh = find_program('docs_pages_fix.sh')
|
||||
gir_docs_pages_fix = custom_target('g-ir-Pika-' + lang + '-pages-fix',
|
||||
input: [ gir_docs_pages ],
|
||||
output: [ 'Pika-' + lang + '-pages-fix' ],
|
||||
command: [
|
||||
docs_pages_fix_sh,
|
||||
'@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version + '/Pika.Procedure.add_menu_path.page',
|
||||
'@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version + '/Pika.checks_get_colors.page',
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
gir_docs_cache = custom_target('g-ir-Pika-' + lang + '-cache',
|
||||
input: [ gir_docs_pages_fix ],
|
||||
output: [ 'Pika-' + lang + '-cache' ],
|
||||
command: [
|
||||
yelp_build, 'cache',
|
||||
'-o', '@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version + '/index.cache',
|
||||
'@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version,
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
gir_docs_html = custom_target('g-ir-Pika-' + lang + '-html',
|
||||
input: [ gir_docs_cache ],
|
||||
output: [ 'Pika-' + lang + '-html' ],
|
||||
# TODO: `output` needs to be complete for installation to work. So
|
||||
# we need to figure out how to install the generated files (listing
|
||||
# all of them is a crazy idea, but maybe we can generate the
|
||||
# expected list somehow? Maybe even using the .def file which is
|
||||
# already an exhaustive listing would be a good idea?
|
||||
# Also where should we install exactly?
|
||||
#install_dir: prefix / pikadatadir / 'g-ir-docs/html/' + lang + '/Pika',
|
||||
#install: true,
|
||||
command: [
|
||||
'yelp-build', 'html',
|
||||
'-o', '@OUTDIR@' + '/html/' + lang + '/Pika-' + pika_api_version,
|
||||
'@OUTDIR@' + '/pages/' + lang + '/Pika-' + pika_api_version,
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
## PikaUi module ##
|
||||
|
||||
gir_ui_docs_pages = custom_target('g-ir-PikaUi-' + lang + '-pages',
|
||||
depends: [ gir_docs_dir, libpikaui_gir ],
|
||||
input: [ libpikaui_gir[0] ],
|
||||
output: [ 'PikaUi-' + lang + '-pages' ],
|
||||
command: [
|
||||
gir_doc_tool,
|
||||
'-I', prefix / 'share/gir-1.0/',
|
||||
'-I', meson.project_build_root() / 'libpika',
|
||||
'--language=' + lang,
|
||||
'-o', '@OUTDIR@' + '/pages/' + lang + '/PikaUi-' + pika_api_version,
|
||||
meson.project_build_root() / '@INPUT@'
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
gir_ui_docs_cache = custom_target('g-ir-PikaUi-' + lang + '-cache',
|
||||
input: [ gir_ui_docs_pages ],
|
||||
output: [ 'PikaUi-' + lang + '-cache' ],
|
||||
command: [
|
||||
yelp_build, 'cache',
|
||||
'-o', '@OUTDIR@' + '/pages/' + lang + '/PikaUi-' + pika_api_version + '/index.cache',
|
||||
'@OUTDIR@' + '/pages/' + lang + '/PikaUi-' + pika_api_version,
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
gir_ui_docs_html = custom_target('g-ir-PikaUi-' + lang + '-html',
|
||||
input: [ gir_ui_docs_cache ],
|
||||
output: [ 'PikaUi-' + lang + '-html' ],
|
||||
#install_dir: prefix / pikadatadir / 'g-ir-docs/html/' + lang + '/PikaUi',
|
||||
#install: true,
|
||||
command: [
|
||||
'yelp-build', 'html',
|
||||
'-o', '@OUTDIR@' + '/html/' + lang + '/PikaUi-' + pika_api_version,
|
||||
'@OUTDIR@' + '/pages/' + lang + '/PikaUi-' + pika_api_version,
|
||||
],
|
||||
build_by_default: true)
|
||||
|
||||
endforeach
|
||||
|
||||
## TODO: a unit test using yelp-check would be useful.
|
131
devel-docs/gitlab-mr.md
Normal file
@ -0,0 +1,131 @@
|
||||
# Merge Request tricks
|
||||
|
||||
By default, a Merge Request pipeline would only build PIKA with
|
||||
autotools, meson and for Windows 64-bit (similarly to normal commits).
|
||||
|
||||
You might want to actually generate easy-to-install builds, in
|
||||
particular if you want it to be testable for non-developers, or various
|
||||
other reasons. Making a full flatpak or Windows installer can actually
|
||||
be quite time-consuming on a personal computer.
|
||||
|
||||
☣️ We remind that these packages are built on-top of development code
|
||||
(i.e. work-in-progress and potentially unstable codebase likely
|
||||
containing critical bugs) with additional code which can be contributed
|
||||
by anyone (any anonymous person is allowed to propose patches as merge
|
||||
requests not only known team members).
|
||||
Therefore you should always check the merge request changes before
|
||||
running the code and never blindly trust that it is harmless. In any
|
||||
case, run these builds at your own risk. ☢️
|
||||
|
||||
## Generating a Windows installer for merge request code
|
||||
|
||||
If you add the label `5. Windows Installer` in a MR, then trigger a
|
||||
pipeline (for instance by rebasing), it will add a Windows installer
|
||||
creation to the pipeline. Once the pipeline ends, the installer can be
|
||||
found by:
|
||||
|
||||
- clicking the pipeline ID.
|
||||
- In the "Distribution" stage, click the "win-installer-nightly" job.
|
||||
- Then click the "Browse" button.
|
||||
- Navigate to `build/installer/_Output/`.
|
||||
- Then click the `pika-<version>-setup.exe` file to download the
|
||||
installer.
|
||||
|
||||
## Generating a flatpak for merge request code
|
||||
|
||||
If you add the label `5. Flatpak package` in a MR, then trigger a
|
||||
pipeline for instance by rebasing), it will add a flatpak creation to
|
||||
the pipeline. Once the pipeline ends, the flatpak can be installed by:
|
||||
|
||||
- clicking the pipeline ID.
|
||||
- In the "Pika" stage, click the "flatpak" job.
|
||||
- Then click the "Browse" button.
|
||||
- Click the `pika-git.flatpak` file to download it.
|
||||
- Locally run: `flatpak install --user ./pika-git.flatpak`
|
||||
It should propose you to install the flatpak, allowing you to test.
|
||||
- After testing, you can uninstall with: `flatpak remove technology.heckin.PIKA//master`
|
||||
|
||||
## Reviewing MR branches
|
||||
|
||||
Reviewing merge requests on the Gitlab interface often leads to poor
|
||||
review, because:
|
||||
|
||||
- It doesn't show tabs, trailing whitespaces and other space issues
|
||||
which a well-configured CLI git would usually emphasize with colors.
|
||||
- The commit history is not emphasized, only the final results, but it's
|
||||
very important to check individual commits, as well as usable commit
|
||||
messages.
|
||||
- It's anyway usually much easier to review patches on your usual
|
||||
workflow environment rather than in a hard-to-use web interface.
|
||||
|
||||
There are ways to work on your local environments.
|
||||
|
||||
### Fetching MR branches automatically (read-only)
|
||||
|
||||
This first one is more of a trick, but an incredibly useful one.
|
||||
Unfortunately it is read-only, so it means you can review but not edit
|
||||
the MR yourself. Nevertheless since having to edit a MR should be the
|
||||
exception, not the rule, it's actually not too bad.
|
||||
|
||||
Edit your `.git/config` by adding a second "fetch =" rule to the
|
||||
"origin" remote. It should read:
|
||||
|
||||
```
|
||||
[remote "origin"]
|
||||
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||
fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*
|
||||
url = git@ssh.gitlab.gnome.org:GNOME/pika.git
|
||||
```
|
||||
|
||||
From now on, when you `git pull` or `git fetch` the origin remote, any
|
||||
new or updated merge request will also be fetched. \o/
|
||||
|
||||
### Pushing to a third-party MR branch
|
||||
|
||||
There are cases when you want to push to the MR branch. It should stay
|
||||
rare occasions, but it can be for instance when the contributor seems
|
||||
stuck and doesn't know how to do some things; or maybe one doesn't
|
||||
understand instructions; sometimes also some contributors disappear
|
||||
after pushing their patch and never answer to review anymore.
|
||||
|
||||
When this happen, you could merge the commit and fix it immediately
|
||||
after (but it's never good to leave the repo in a bad state, even for
|
||||
just a few minutes). You could also apply, fix and push the fixed
|
||||
commits directly, but then the MR has to be closed and it doesn't look
|
||||
like it was applied (which is not the end of the world, but it's still
|
||||
nicer to show proper status on which patches were accepted or not).
|
||||
Moreover you would not be able to pass the CI build.
|
||||
|
||||
So we will fetch the remote yet without naming the remote:
|
||||
|
||||
- Click the "Check out branch" button below the merge request
|
||||
description. Gitlab gives you instructions but we will only use the
|
||||
first step ("Fetch and check out the branch for this merge request").
|
||||
For instance if contributor `xyz` created the branch `fix-bug-123` on
|
||||
their own remote, you would run:
|
||||
|
||||
```
|
||||
git fetch "git@ssh.gitlab.gnome.org:xyz/pika.git" 'fix-bug-123'
|
||||
git checkout -b 'xyz/fix-bug-123' FETCH_HEAD
|
||||
```
|
||||
|
||||
- Now that you are in a local branch with their code, make your fix, add
|
||||
a local commit.
|
||||
|
||||
- Finally push to the contributor's own remote with the call:
|
||||
|
||||
```
|
||||
git push git@ssh.gitlab.gnome.org:xyz/pika.git xyz/fix-bug-123:fix-bug-123
|
||||
```
|
||||
|
||||
This assumes that the contributor checked the option "*Allow commits
|
||||
from members who can merge to the target branch.*" (which we ask
|
||||
contributors to check, and it's set by default)
|
||||
|
||||
- Now check the MR page. It will normally be updated with your new
|
||||
commit(s) and a new pipeline should be triggered.
|
||||
|
||||
- Finally if you don't need the local branch anymore, you may delete it
|
||||
locally. The nice thing is that since you didn't name the remote, it
|
||||
doesn't pollute your git output and all data will be simply disposed
|
||||
of the next time `git gc` runs (implicitly or explicitly).
|
176
devel-docs/icons.md
Normal file
@ -0,0 +1,176 @@
|
||||
# Icon themes for PIKA
|
||||
|
||||
## Released Themes
|
||||
|
||||
PIKA 3.0 comes with 3 icon themes:
|
||||
|
||||
1. **Symbolic**: the default icon theme which is vector and which will
|
||||
be automatically recolored to your theme colors.
|
||||
|
||||
We follow [GNOME
|
||||
guidelines](https://developer.gnome.org/hig/guidelines/ui-icons.html)
|
||||
when possible.
|
||||
|
||||
2. **Color**: the color icon theme, also designed with vector graphics,
|
||||
yet it won't be recolored.
|
||||
|
||||
3. **Legacy**: icon theme which contains the old PIKA 2.8's raster
|
||||
icons (mostly untouched ever since PIKA 2.10). It is not maintained
|
||||
anymore and we are not expecting new icons for Legacy. Yet since we
|
||||
keep them in the source tree for now, we would accept updates.
|
||||
|
||||
The Symbolic icon theme is our main target since they are considered
|
||||
better suited for graphics work (less visual distraction). Color icons
|
||||
are kept as fall-back since some users prefer them.
|
||||
|
||||
Vector icons are now prefered because they are much less maintenance.
|
||||
For instance, we do not need to double, triple (or more) every icon for
|
||||
the various sizes they are needed in, and double this amount again to
|
||||
handle high density displays.
|
||||
Yet if anyone cared enough for a complete raster icon theme to get the
|
||||
*Legacy* icon theme back in shape, add high density icon variants and
|
||||
stay around, it could even get back to maintenance state. Be aware it is
|
||||
a lot of work and we'd expect contributors ready to maintain support to
|
||||
the icons as the software evolve.
|
||||
|
||||
## Adding new icons
|
||||
|
||||
- Add new icons in the single SVG file inside their respective
|
||||
directories, i.e.
|
||||
[symbolic-scalable.svg](/icons/Symbolic/symbolic-scalable.svg) for
|
||||
symbolic icons and
|
||||
[color-scalable.svg](icons/Color/color-scalable.svg) for color icons.
|
||||
|
||||
A single file allows easier reuse of material, and easy overview of
|
||||
all existing icons which simplifies consistent styling…
|
||||
|
||||
- The contents of the SVG file should be organized for easy management
|
||||
and easy contribution. You can visually group similar icons, make use
|
||||
of layers, whatever is necessary for organization.
|
||||
|
||||
- You should group all parts of a single icon into a single object and
|
||||
id this object with the icon name. For instance the object containing
|
||||
the Move Tool icon should be id-ed: "pika-tool-move".
|
||||
|
||||
- Make sure the object has the right expected size. A good trick is to
|
||||
group with a square of the right size, made invisible.
|
||||
|
||||
- Export the icon as SVG into the `scalable/` directory.
|
||||
|
||||
Ideally this step should be done at build time, but we could not find
|
||||
yet a reliable way to extract icons out of the single SVG file without
|
||||
using crazy build dependencies (like Inkscape). So this is done by hand
|
||||
for the time being.
|
||||
|
||||
Please make sure that you provide both the Symbolic as well as the Color
|
||||
icons. You are welcome to add a raster version for Legacy, but this is
|
||||
not mandatory anymore.
|
||||
|
||||
- Add the icons in relevant listing files in `icons/icon-lists/` then
|
||||
run `tools/generate-icon-makefiles.py` which will regenerate files for
|
||||
the autotools build integrating your new icons and `touch` the
|
||||
`meson.build` files to make sure the next build will trigger a
|
||||
reconfiguration. The meson build indeed also uses the same listing
|
||||
files so you only have to add your icon names in the right categories,
|
||||
run the script and you are done.
|
||||
|
||||
|
||||
### Pixel perfection
|
||||
|
||||
Even as vector images, icons could be pixel-perfect when possible.
|
||||
Therefore the first step before making an icon is to determine which
|
||||
size it is supposed to appear at.
|
||||
If the icon could appear in several sizes:
|
||||
|
||||
- if the sizes are multiples, just design the smaller size. The bigger
|
||||
icon will stay pixel-perfect when scaled by a multiple. So for instance,
|
||||
if you want the icon to be 12x12 and 24x24, just design the 12x12 icon.
|
||||
|
||||
- of course, if the size difference is big enough, you may want to
|
||||
create a new version with added details, even when this is a multiple
|
||||
(i.e. 12x12 and 192x192 may be different designs). These are design
|
||||
choices.
|
||||
|
||||
- when sizes are no multiple (i.e. 16x16 and 24x24), it is preferred to
|
||||
have 2 pixel-perfect versions.
|
||||
|
||||
- if time is missing, creating the smaller size only is a first step
|
||||
and is acceptable.
|
||||
|
||||
Note that since our maintained icons are currently vector, we only
|
||||
design them once and scale the icon for all sizes at runtime. This is an
|
||||
easy-maintenance choice. We are not against pixel-perfection, even of
|
||||
vector icons, but once again if a contributor wants to embark in such a
|
||||
journey, we'd expect them to stay for continuous maintenance.
|
||||
|
||||
### Colors in Symbolic icon theme
|
||||
|
||||
By default, colors in the Symbolic icon theme don't matter as they will
|
||||
be changed by the foreground and background colors of the theme. Yet it
|
||||
is still a good idea to use the same colors for all icons in
|
||||
`icons/Symbolic/symbolic-scalable.svg` to keep visual consistency when
|
||||
reviewing icons.
|
||||
|
||||
Furthermore, there is a trick to apply hard-coded colors (i.e. which
|
||||
won't be recolored): add the `!important` flag to the color in the
|
||||
`style` SVG parameter. Then GTK will not recolor this color.
|
||||
|
||||
It is to be noted that (last we tested), Inkscape was not able to keep
|
||||
this flag, so you will likely have to edit the file manually in a text
|
||||
or XML editor.
|
||||
|
||||
For instance
|
||||
"[pika-default-colors](icons/Symbolic/scalable/pika-default-colors-symbolic.svg)"
|
||||

|
||||
and
|
||||
"[pika-toilet-paper](icons/Symbolic/scalable/pika-toilet-paper-symbolic.svg)"
|
||||

|
||||
icons contain such tricks.
|
||||
For the first one, the default colors was black and white in this
|
||||
specific order (it made no sense to invert them or worse to transform
|
||||
them into whatever other colors the theme might be using). For the
|
||||
second, it was considered inappropriate by some contributors to generate
|
||||
black toilet papers.
|
||||
|
||||
Other such examples are
|
||||
[pika-color-picker-black](icons/Symbolic/scalable/pika-color-picker-black-symbolic.svg),
|
||||

|
||||
[pika-color-picker-gray](icons/Symbolic/scalable/pika-color-picker-gray-symbolic.svg)
|
||||

|
||||
and
|
||||
[pika-color-picker-white](icons/Symbolic/scalable/pika-color-picker-white-symbolic.svg).
|
||||
.
|
||||
Since they are designing specific colors, it doesn't make sense to let
|
||||
any recoloring happen.
|
||||
|
||||
### Sizes
|
||||
|
||||
Some known sizes:
|
||||
|
||||
- tool icons: 16x16 and 22x22.
|
||||
- dock tab icons: 16x16 and 24x24.
|
||||
- menu icons: 16x16.
|
||||
[…]
|
||||
|
||||
## Testing icons
|
||||
### Showing menu icons and buttons
|
||||
|
||||
Menu items and buttons are not supposed to have icons any longer (except
|
||||
for buttons with no label at all). Yet our actions have icons and some
|
||||
desktop environments would enable them in menus and buttons regardless.
|
||||
To test how it looks on systems which do so, set the environment
|
||||
variable `PIKA_ICONS_LIKE_A_BOSS`.
|
||||
|
||||
For instance, start PIKA like this:
|
||||
|
||||
PIKA_ICONS_LIKE_A_BOSS=1 pika-2.99
|
||||
|
||||
### Playing with low/high density
|
||||
|
||||
To test high (or low) density icons, without having to change the
|
||||
scaling factor of your whole desktop, just change the `GDK_SCALE`
|
||||
environment variable.
|
||||
For instance, run PIKA like this to simulate a scaling factor of 2
|
||||
(every icons and text would typically double):
|
||||
|
||||
GDK_SCALE=2 pika-2.99
|
51
devel-docs/includes.txt
Normal file
@ -0,0 +1,51 @@
|
||||
includes.txt
|
||||
============
|
||||
|
||||
The include policy for the files in app/ is as follows:
|
||||
|
||||
Each subdirectory has a <module>-types.h file which defines the type
|
||||
space known to this module. All .c files in the directory include this
|
||||
(and only this) <module>-types.h file. <foo>-types.h files from other
|
||||
modules are included from the <module>-types.h file only. This way
|
||||
<module>-types.h becomes the only place where the namespace known to a
|
||||
module is defined.
|
||||
|
||||
|
||||
***** .h files *****
|
||||
|
||||
No .h file includes anything, with two exceptions:
|
||||
|
||||
- objects include their immediate parent class
|
||||
- if the header uses stuff like time_t (or off_t), it includes
|
||||
<time.h> (or <sys/types.h>). This only applies to system stuff!
|
||||
|
||||
|
||||
***** .c files *****
|
||||
|
||||
The include order of all .c files of a module is as follows:
|
||||
|
||||
/* example of a .c file from app/core */
|
||||
|
||||
#include "config.h" /* always and first */
|
||||
|
||||
#include <glib.h> /* *only* needed if the file needs stuff */
|
||||
/* like G_OS_WIN32 for conditional inclusion */
|
||||
/* of system headers */
|
||||
|
||||
#include <system headers> /* like <stdio.h> */
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
#include "libpikafoo/pikafoo.h" /* as needed, e.g. "libpikabase/pikabase.h" */
|
||||
#include "libpikabar/pikabar.h"
|
||||
|
||||
#include "core-types.h" /* and _no_ other foo-types.h file */
|
||||
|
||||
#include "base/foo.h" /* files from modules below this one */
|
||||
#include "base/bar.h"
|
||||
|
||||
#include "pika.h" /* files from this module */
|
||||
#include "pikaimage.h"
|
||||
#include "pikawhatever.h"
|
||||
|
||||
#include "pika-intl.h" /* if needed, *must* be the last include */
|
209
devel-docs/interpreters.txt
Normal file
@ -0,0 +1,209 @@
|
||||
# Interpreters for PIKA plugins
|
||||
|
||||
|
||||
|
||||
## About this document
|
||||
|
||||
This describes how PIKA invokes interpreters for PIKA plugin files.
|
||||
|
||||
This doesn't discuss the architecture of PIKA's interpreters,
|
||||
or how to write an interpreted plugin.
|
||||
|
||||
The audience is mainly PIKA developers.
|
||||
This may also interest users who want to use different interpreters.
|
||||
|
||||
|
||||
## Brief summary
|
||||
|
||||
On Linux and MacOS, a shebang in a PIKA plugin text file
|
||||
is enough to indicate what interpreter to start.
|
||||
On Windows, you also need an .interp file installed with PIKA.
|
||||
|
||||
It can get complicated;
|
||||
there are many combinations of envirnoment variables, shebangs, file suffixes, and .interp files that can work.
|
||||
|
||||
*To insure a PIKA interpreted plugin works across platforms,
|
||||
it should have a shebang.*
|
||||
|
||||
*Except that ScriptFu plugin files installed to /scripts do not need a shebang
|
||||
since the ScriptFu extension reads them.*
|
||||
|
||||
## Partial history of interpreters in PIKA
|
||||
|
||||
Rarely are interpreters addded to PIKA.
|
||||
PIKA 2 offers Perl, Scheme, and Python2 interpreters.
|
||||
PIKA 3 offers Python3, lua, javascript, and the pika-script-fu-interpreter interpreters.
|
||||
|
||||
|
||||
## Background
|
||||
|
||||
An interpreter usually reads a text file.
|
||||
A user often launches an interpreter and passes a text file.
|
||||
But users can also double-click on a text file to launch the corresponding interpreter.
|
||||
|
||||
Similarly, PIKA launches an interpreter on PIKA plugin text files.
|
||||
PIKA must figure out the "corresponding" interpreter.
|
||||
|
||||
The general mechanism for launching interpreters from their text files is built into the operating system.
|
||||
On Linux and MacOS, the mechanism is called a shebang or sh-bang.
|
||||
On Windows, the mechanism "associates" file extensions with programs.
|
||||
|
||||
PIKA uses similar mechanisms to launch interpreters.
|
||||
See the code in /app/plug-ins/pikainterpreterdb.c .
|
||||
*The exception is the ScriptFu extension.
|
||||
PIKA starts it when PIKA starts and it reads its ".scm" plugin files from the /scripts directory without benefit
|
||||
of the shebang mechanism.*
|
||||
|
||||
PIKA uses the mechanism when it queries plugin files at startup.
|
||||
Subsequently, PIKA knows the interpreter to launch,
|
||||
for example when a user clicks on a menu item implemented by an interpreter.
|
||||
A user should not click on a PIKA plugin file in a file browser;
|
||||
only one of the PIKA apps should launch interpreted PIKA plugin files.
|
||||
|
||||
|
||||
## Platform differences
|
||||
|
||||
On Linux and MacOS, you simply need a shebang in a plugin text file.
|
||||
|
||||
On Windows, you must also define an .interp file.
|
||||
The .interp files are part of PIKA's installation on Windows.
|
||||
The .interp files are built when the Windows installer is built.
|
||||
See the source file: /build/windows/installer/pika3264.iss .
|
||||
|
||||
A user can optionally create .interp files on Linux and MacOS.
|
||||
But they are not usually part of a Linux installation.
|
||||
Sophisticated users can edit .interp files to change which interpreters PIKA launches.
|
||||
|
||||
|
||||
## shebangs
|
||||
|
||||
A shebang is text in the first line of a text file to be interpreted.
|
||||
A shebang starts with "#!",
|
||||
followed by the name or path of an interpreter,
|
||||
or followed by "/usr/bin/env", a space, and the name or path of an interpreter.
|
||||
|
||||
!!! Shebangs for PIKA plugins always use UNIX notation, i.e. forward slashes in path strings.
|
||||
Even on Windows, the shebangs are in UNIX notation.
|
||||
|
||||
Recommended examples for PIKA 3 (see repo directory /extensions/goat-exercises):
|
||||
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env luajit
|
||||
#!/usr/bin/env gjs
|
||||
#!/usr/bin/env pika-script-fu-interpreter-3.0
|
||||
|
||||
Other examples:
|
||||
|
||||
#!python
|
||||
#!/usr/bin/python
|
||||
#!/usr/bin/env python
|
||||
|
||||
Whether the other examples actually work depends on:
|
||||
|
||||
- the platform
|
||||
- the user's environment, namely search PATH's
|
||||
- any .interp files
|
||||
|
||||
|
||||
## .interp files
|
||||
|
||||
Again, .interp files are necessary on Windows.
|
||||
They tell PIKA which executable interpreter to launch for a PIKA plugin text file.
|
||||
|
||||
You usually have one .interp file for each interpreter.
|
||||
For example:
|
||||
- python.interp
|
||||
- lua.interp
|
||||
- pika-script-fu-interpreter.interp
|
||||
|
||||
The repo file /data/interpreters/default.interp is a non-functioning template
|
||||
for a <foo>.interp file.
|
||||
|
||||
.interp files are installed on Windows to, for example:
|
||||
|
||||
C:\Users\foo\AppData\Programs\PIKA 3.0\lib\pika\3.0\interpreters
|
||||
|
||||
|
||||
interp files have three kinds of lines:
|
||||
- "program" in the form lhs=rhs
|
||||
- "extension" in the "binfmt" format
|
||||
- "magic" in the "binfmt" format
|
||||
|
||||
### "program" lines in an .interp file
|
||||
|
||||
These lines associate a shebang with a path to an executable.
|
||||
|
||||
These are in the form: "lhs=rhs"
|
||||
where lhs/rhs denotes "left hand side" and "right hand side."
|
||||
|
||||
The lhs matches the full text of a shebang after the "#!"
|
||||
For example, the lhs can be "/usr/bin/env python", having a space.
|
||||
Since a shebang is always in UNIX notation, any slashes are forward.
|
||||
|
||||
The rhs specifies a path to an interpreter.
|
||||
The rhs on the Windows platform is in Windows notation, using back slashes.
|
||||
For example, the rhs can be "C:\Users\foo\AppData\Programs\PIKA 3.0\bin\python"
|
||||
|
||||
|
||||
### "extension" lines in an .interp file
|
||||
|
||||
These lines associate a three-letter (sic) file extension (suffix) with a path to an executable.
|
||||
|
||||
These lines are in binfmt format.
|
||||
See https://en.wikipedia.org/wiki/Binfmt_misc.
|
||||
|
||||
Informally the format is: ":name:type:offset:magic: mask:interpreter:flags"
|
||||
!!! Note the field delimiter is usually ":" but can be another character.
|
||||
PIKA parses the binfmt using the first character as the delimiter.
|
||||
The first field is a name or identifier and has little significance.
|
||||
The second field is an "E".
|
||||
The third, fifth, and seventh fields are usually empty.
|
||||
The fourth field is an up-to-three letter suffix.
|
||||
The sixth field "interpreter" is a name or path to an executable interpreter.
|
||||
|
||||
If the sixth field is a Windows path that has a ":"
|
||||
then the fields must be delimited with another character, say a ",".
|
||||
|
||||
Examples:
|
||||
|
||||
:python:E::py::python3:
|
||||
:luajit:E::lua::luajit:
|
||||
,python,E,,py,,C:\Users\foo\AppData\PIKA 3.0\bin\python3,
|
||||
|
||||
Note the examples are not necessarily working examples.
|
||||
They might not work if the name or path is not found,
|
||||
for example if luajit was not installed to the Windows system directory of executables.
|
||||
|
||||
Note one example shows a path in Windows notation,
|
||||
having a ":", back slashes, and a space in the path.
|
||||
|
||||
|
||||
### "magic" lines in an .interp file
|
||||
|
||||
These lines associate "magic" bytes (inside a binary file) with a path to an executable.
|
||||
|
||||
These lines are in binfmt format.
|
||||
The second field is an "M".
|
||||
|
||||
We won't discuss these further, since they are little used.
|
||||
Binary files on Windows might not have "magic" bytes.
|
||||
Usually interpreters read text files, and rarely binary files.
|
||||
|
||||
|
||||
## Building .interp files for windows
|
||||
|
||||
If a PIKA developer adds an interpreter to the PIKA package,
|
||||
they must modify PIKA's build for Windows
|
||||
to ensure proper .interp files are installed.
|
||||
|
||||
See the repo file: /build/windows/installer/pika3264.iss .
|
||||
|
||||
For the convenience of users, we usually install an .interp file having many lines.
|
||||
Only one "program" line is needed if users only install canonical plugin text files
|
||||
having a recommended shebang
|
||||
using the actual filename of the target interpreter.
|
||||
But since users may install non-canonical plugin text files by copying files,
|
||||
for convenience we have more lines in the .interp file.
|
||||
An extra "extension" line allows plugin text files without any shebang but a proper extension.
|
||||
An extra "program" line allows plugin text files
|
||||
having shebangs with alternate names for an interpreter.
|
17
devel-docs/meson.build
Normal file
@ -0,0 +1,17 @@
|
||||
devel_docs_build_root = meson.current_build_dir()
|
||||
|
||||
scan_args_common = [
|
||||
'--deprecated-guards=PIKA_DISABLE_DEPRECATED',
|
||||
]
|
||||
|
||||
mkdb_args_common = [
|
||||
'--name-space=pika',
|
||||
]
|
||||
|
||||
if gi_docgen.found() and have_gobject_introspection
|
||||
subdir('reference')
|
||||
endif
|
||||
|
||||
if get_option('g-ir-doc')
|
||||
subdir('g-ir-docs')
|
||||
endif
|
32
devel-docs/os-support.txt
Normal file
@ -0,0 +1,32 @@
|
||||
## PIKA's Operating System Support
|
||||
|
||||
PIKA is available on a wide range of operating systems.
|
||||
As a general rule, we should stop supporting a platform as soon as the
|
||||
publisher stops supporting it, or if it is nearly not used anymore.
|
||||
|
||||
There is no accurate rule though, and it also mostly depends on what the
|
||||
developers maintaining PIKA for this platform will decide.
|
||||
|
||||
### GNU/Linux, *BSD…
|
||||
|
||||
Until PIKA 3.0 release, Debian 12 "bookworm" stable will be our baseline target.
|
||||
I.e. that we can bump a minimum dependency version only if it is in Debian
|
||||
bookworm.
|
||||
|
||||
After PIKA 3.0 release, we might get back to depend on Debian Testing.
|
||||
|
||||
### macOS
|
||||
|
||||
Compatibility with 10.13 and over.
|
||||
|
||||
Hardware:
|
||||
* x86_64 (Intel)
|
||||
* ARM 64-bit (Apple Silicon)
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 10 and over.
|
||||
|
||||
Hardware:
|
||||
* x86 32 and 64-bit
|
||||
* ARM 64-bit (experimental)
|
316
devel-docs/parasites.txt
Normal file
@ -0,0 +1,316 @@
|
||||
|
||||
PARASITE REGISTRY
|
||||
=================
|
||||
|
||||
This document describes parasites in PIKA.
|
||||
|
||||
|
||||
Table of contents
|
||||
-----------------
|
||||
Parasite registry
|
||||
Table of contents
|
||||
Audience
|
||||
|
||||
1. Namespace
|
||||
|
||||
2. Known prefixes
|
||||
|
||||
3. Known global parasites
|
||||
|
||||
4. Known image parasites
|
||||
|
||||
5. Known layer/drawable parasites
|
||||
|
||||
6. Parasite format
|
||||
|
||||
|
||||
Audience
|
||||
--------
|
||||
This document is designed for the convenience of PIKA developers.
|
||||
It does not need to concern users.
|
||||
|
||||
>>>> If your plug-in or script writes parasites, please
|
||||
>>>> amend this file in the Git repository or submit patches to
|
||||
>>>> pika-developer-list@gnome.org
|
||||
|
||||
|
||||
1. NAMESPACE
|
||||
============
|
||||
|
||||
Plug-in-specific data should be prefixed by the plug-in function name and
|
||||
a slash, i.e. private data of plug_in_displace should be named like:
|
||||
|
||||
plug_in_displace/data1
|
||||
plug_in_displace/data2
|
||||
etc.
|
||||
|
||||
Global data follows no strict rules.
|
||||
|
||||
|
||||
2. KNOWN PREFIXES
|
||||
=================
|
||||
|
||||
"tiff" : The standard PIKA TIFF plugin
|
||||
"jpeg" : The standard PIKA JPEG plugin
|
||||
"png" : The standard PIKA PNG plugin
|
||||
"dcm" : The standard PIKA DICOM plugin
|
||||
"pika" : For common and standard parasites
|
||||
|
||||
|
||||
3. KNOWN GLOBAL PARASITES
|
||||
=========================
|
||||
|
||||
"jpeg-save-defaults" (GLOBAL, PERSISTENT)
|
||||
Default save parameters used by the JPEG plug-in.
|
||||
|
||||
"png-save-defaults" (GLOBAL, PERSISTENT)
|
||||
Default save parameters used by the PNG plug-in.
|
||||
|
||||
"<plug-in>/_fu_data" (GLOBAL, IMAGE, DRAWABLE, PERSISTENT)
|
||||
The Pika::Fu module (Perl) might store the arguments of the
|
||||
last plug-in invocation. It is usually attached to images,
|
||||
but might also be found globally. The data format is either
|
||||
pure character data (Data::Dumper) or a serialized data
|
||||
stream created by Storable::nfreeze.
|
||||
|
||||
"exif-orientation-rotate" (GLOBAL, PERSISTENT)
|
||||
Whether a load plug-in should automatically rotate the image
|
||||
according to the orientation specified in the EXIF data. This
|
||||
has values "yes" or "no". If the parasite is not set, the
|
||||
plug-in should ask the user what to do. This parasite may be
|
||||
removed in a future version (assuming always yes).
|
||||
|
||||
|
||||
4. KNOWN IMAGE PARASITES
|
||||
========================
|
||||
|
||||
"pika-comment" (IMAGE, PERSISTENT)
|
||||
Standard GIF-style image comments. This parasite should be
|
||||
human-readable text in UTF-8 encoding. A trailing \0 might
|
||||
be included and is not part of the comment. Note that image
|
||||
comments may also be present in the "pika-metadata" parasite.
|
||||
|
||||
"pika-brush-name" (IMAGE, PERSISTENT)
|
||||
A string in UTF-8 encoding specifying the name of a PIKA brush.
|
||||
Currently, the gbr plug-in uses this parasite when loading and
|
||||
saving .gbr files. A trailing \0 might be included and is not
|
||||
part of the name.
|
||||
|
||||
"pika-brush-pipe-name" (IMAGE, PERSISTENT)
|
||||
A string in UTF-8 encoding specifying the name of a PIKA brush
|
||||
pipe. Currently, the gih plug-in uses this parasite when loading and
|
||||
saving .gih files. A trailing \0 might be included and is not
|
||||
part of the name.
|
||||
|
||||
"pika-brush-pipe-parameters" (IMAGE, PERSISTENT)
|
||||
This is all very preliminary:
|
||||
|
||||
A string, containing parameters describing how an brush pipe
|
||||
should be used. The contents is a space-separated list of
|
||||
keywords and values. The keyword and value are separated by a
|
||||
colon.
|
||||
|
||||
This parasite is currently attached to an image by the psp
|
||||
plug-in when it loads a .tub file (Paint Shop Pro picture
|
||||
tube). It is used (first attached with values asked from the
|
||||
user, if nonexistent) by the gpb plug-in when it saves a .gih
|
||||
file. The .gih file contains the same text in it.
|
||||
|
||||
The keywords are:
|
||||
ncells: the number of brushes in the brush pipe
|
||||
step: the default spacing for the pipe
|
||||
dim: the dimension of the pipe. The number of cells
|
||||
in the pipe should be equal to the product
|
||||
of the ranks of each dimension.
|
||||
cols: number of columns in each layer of the image,
|
||||
to be used when editing the pipe as a PIKA image
|
||||
rows: ditto for rows. Note that the number of columns and rows
|
||||
not necessarily are identical to the ranks of the
|
||||
dimensions of a pipe, but in the case of two-
|
||||
and three-dimensional pipes, it probably is.
|
||||
rank0, rank1, ...: (one for each dimension): the index range
|
||||
for that dimension
|
||||
placement: "default", "constant" or "random". "constant" means
|
||||
use the spacing in the first brush in the pipe.
|
||||
"random" means perturb that with some suitable
|
||||
random number function. (Hmm, would it be overdoing it
|
||||
if the pipe also could specify what random function
|
||||
and its parameters...?)
|
||||
sel0, sel1, ...: "default", "random", "incremental", "angular",
|
||||
"pressure", "velocity", and whatever else suitable we might
|
||||
think of ;-) Determines how one index from each dimension is
|
||||
selected (until we have pinpointed the brush to use).
|
||||
|
||||
"pika-image-grid" (IMAGE, PERSISTENT)
|
||||
The PikaGrid object serialized to a string. Saved as parasite
|
||||
to keep the XCF files backwards compatible. Although pika-1.2
|
||||
does not know how to handle the image grid, it keeps the grid
|
||||
information intact.
|
||||
|
||||
"pika-pattern-name" (IMAGE, PERSISTENT)
|
||||
A string in UTF-8 encoding specifying the name of a PIKA pattern.
|
||||
Currently, the pat plug-in uses this parasite when loading and
|
||||
saving .pat files. A trailing \0 might be included and is not
|
||||
part of the name.
|
||||
|
||||
"tiff-save-options" (IMAGE)
|
||||
The TiffSaveVals structure from the TIFF plugin.
|
||||
|
||||
"jpeg-save-options" (IMAGE)
|
||||
The JpegSaveVals structure from the JPEG plugin.
|
||||
|
||||
"jpeg-exif-data" (IMAGE) (deprecated)
|
||||
The ExifData structure serialized into a uchar* blob from
|
||||
libexif. This is deprecated in favor of "exif-data".
|
||||
|
||||
"jpeg-original-settings" (IMAGE, PERSISTENT)
|
||||
The settings found in the original JPEG image: quality (IJG),
|
||||
color space, component subsampling and quantization tables.
|
||||
These can be reused when saving the image in order to minimize
|
||||
quantization losses and keep the same size/quality ratio.
|
||||
|
||||
"gamma" (IMAGE, PERSISTENT)
|
||||
The original gamma this image was created/saved. For JPEG; this is
|
||||
always one, for PNG it's usually taken from the image data. PIKA
|
||||
might use and modify this. The format is an ascii string with the
|
||||
gamma exponent as a flotingpoint value.
|
||||
|
||||
Example: for sRGB images this might contain "0.45454545"
|
||||
|
||||
"chromaticity" (IMAGE, PERSISTENT)
|
||||
This parasite contains 8 floatingpoint values (ascii, separated by
|
||||
whitespace) specifying the x and y coordinates of the whitepoint, the
|
||||
red, green and blue primaries, in this order.
|
||||
|
||||
Example: for sRGB images this might contain
|
||||
"0.3127 0.329 0.64 0.33 0.3 0.6 0.15 0.06"
|
||||
wx wy rx ry gx gy bx by
|
||||
|
||||
"rendering-intent" (IMAGE, PERSISTENT)
|
||||
This specifies the rendering intent of the image. It's a value
|
||||
between 0 and 3, again in ascii:
|
||||
|
||||
0 - perceptual (e.g. for photographs)
|
||||
1 - relative colorimetric (e.g. for logos)
|
||||
2 - saturation-preserving (e.g. for business charts)
|
||||
3 - absolute colorimetric
|
||||
|
||||
"hot-spot" (IMAGE, PERSISTENT)
|
||||
Use this parasite to store an image's "hot spot". Currently
|
||||
used by the XBM plugin to store mouse cursor hot spots.
|
||||
|
||||
Example: a hot spot at coordinates (5,5) is stored as "5 5"
|
||||
|
||||
"exif-data" (IMAGE, PERSISTENT)
|
||||
The ExifData structure serialized into a character array by
|
||||
libexif (using exif_data_save_data). If a "pika-metadata"
|
||||
parasite is present, it should take precedence over this one.
|
||||
|
||||
"pika-metadata" (IMAGE, PERSISTENT)
|
||||
The metadata associated with the image, serialized as one XMP
|
||||
packet. This metadata includes the contents of any XMP, EXIF
|
||||
and IPTC blocks from the original image, as well as
|
||||
user-specified values such as image comment, copyright,
|
||||
license, etc.
|
||||
|
||||
"icc-profile" (IMAGE, PERSISTENT | UNDOABLE)
|
||||
This contains an ICC profile describing the color space the
|
||||
image was produced in. TIFF images stored in PhotoShop do
|
||||
oftentimes contain embedded profiles. An experimental color
|
||||
manager exists to use this parasite, and it will be used
|
||||
for interchange between TIFF and PNG (identical profiles)
|
||||
|
||||
"icc-profile-name" (IMAGE, PERSISTENT | UNDOABLE)
|
||||
The profile name is a convenient name for referring to the
|
||||
profile. It is for example used in the PNG file format. The
|
||||
name must be stored in UTF-8 encoding. If a file format uses
|
||||
a different character encoding, it must be converted to UTF-8
|
||||
for use as a parasite.
|
||||
|
||||
"decompose-data" (IMAGE, NONPERSISTENT)
|
||||
Starting with PIKA 2.4, this is added to images produced by
|
||||
the decompose plug-in, and contains information necessary to
|
||||
recompose the original source RGB layer from the resulting
|
||||
grayscale layers. It is ascii; a typical example would be
|
||||
"source=2 type=RGBA 4 5 6 7". This means that layer 2 was
|
||||
decomposed in RGBA mode, giving rise to layers 4, 5, 6, and 7.
|
||||
|
||||
"print-settings" (IMAGE, NONPERSISTENT)
|
||||
This parasite is stored by the Print plug-in and holds settings
|
||||
done in the Print dialog. It also has a version field so that
|
||||
changes to the parasite can be done. PIKA 2.4 used version 0.3.
|
||||
The format is GKeyFile. A lot of the contents are identical to
|
||||
what is stored in ~/.pika-2.x/print-settings but the parasite
|
||||
has some additional image-related fields.
|
||||
|
||||
"print-page-setup" (IMAGE, NONPERSISTENT)
|
||||
This parasite is stored by the Print plug-in and holds settings
|
||||
done in the Page Setup dialog. The format is GKeyFile as created
|
||||
from GtkPageSetup. The content is identical to what is stored in
|
||||
~/.pika-2.x/print-page-setup.
|
||||
|
||||
"dcm/XXXX-XXXX-AA" (IMAGE, PERSISTENT)
|
||||
These parasites are stored by the Dicom plug-in and hold the DICOM
|
||||
element information for that image. The format is raw binary data
|
||||
as read from the original image.
|
||||
where: XXXX is a 4-digit ascii encoded hexadecimal number
|
||||
AA is a two character ascii value representing the Dicom
|
||||
element's Value Representation (VR)
|
||||
|
||||
|
||||
5. KNOWN LAYER/DRAWABLE PARASITES
|
||||
=================================
|
||||
|
||||
"pika-text-layer" (LAYER, PERSISTENT)
|
||||
The associated PikaText object serialized to a string. For
|
||||
convenience the string is terminated by a trailing '\0'.
|
||||
The idea of using a parasite for text layers is to keep the XCF
|
||||
files backward compatible. Although pika-1.2 doesn't know how
|
||||
to handle the text layer, it keeps the parasite intact.
|
||||
|
||||
"gfig" (LAYER, PERSISTENT)
|
||||
As of PIKA 2.2, the gfig plug-in creates its own layers, and
|
||||
stores a representation of the figure as a layer parasite.
|
||||
The parasite contains a GFig save file, in an ascii format.
|
||||
If gfig is started while the active layer contains a "gfig"
|
||||
parasite, the contents of the parasite are loaded at startup.
|
||||
|
||||
|
||||
6. PARASITE FORMAT
|
||||
==================
|
||||
|
||||
The parasite data format is not rigidly specified. For non-persistent
|
||||
parasites you are entirely free, as the parasite data does not survive the
|
||||
current pika session. If you need persistent data, you basically have to
|
||||
choose between the following alternatives (also, having some standard for
|
||||
non-persistent data might be fine as well):
|
||||
|
||||
- Cook your own binary data format
|
||||
|
||||
You can invent your own data format. This means that you will either
|
||||
loose totally (consider endian-ness or version-ness issues) or you will
|
||||
get yourself into deep trouble to get it "right" in all cases.
|
||||
|
||||
- Use character (string) data
|
||||
|
||||
Obvious to Perl people but less so to C programmers: just sprintf your
|
||||
data into a string (e.g. "SIZE 100x200 XRES 300 YRES 300") and store
|
||||
that in the parasite, and later sscanf it again. This often solves most
|
||||
of the problems you might encounter, makes for easier debugging and
|
||||
more robustness (consider the case when you add more entries to your
|
||||
persistent data: older plug-ins might be able to read the relevant
|
||||
parts and your application can detect missing fields easily). The
|
||||
drawback is that your data is likely to be larger than a compact binary
|
||||
representation would be. Not much a problem for most applications,
|
||||
though.
|
||||
|
||||
You could also use one parasite per field you store, i.e. foo-size,
|
||||
foo-offset-x, foo-offset-y etc...
|
||||
|
||||
- Use the libpikaconfig serialize functions
|
||||
|
||||
This is a special case of the previous one, using the convenience
|
||||
functions provided by libpikaconfig. If you are not concerned about
|
||||
the size of the string representation of your data, you can use
|
||||
pika_config_serialize_to_string() and other functions to easily
|
||||
convert your data to/from a character string.
|
393
devel-docs/pika-module-dependencies.svg
Normal file
@ -0,0 +1,393 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.26.3 (20100126.1600)
|
||||
-->
|
||||
<!-- Title: _anonymous_0 Pages: 1 -->
|
||||
<svg width="862pt" height="1008pt"
|
||||
viewBox="0.00 0.00 862.00 1008.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph1" class="graph" transform="scale(1 1) rotate(0) translate(4 1004)">
|
||||
<title>_anonymous_0</title>
|
||||
<polygon fill="white" stroke="white" points="-4,5 -4,-1004 859,-1004 859,5 -4,5"/>
|
||||
<!-- app/plug-in -->
|
||||
<g id="node1" class="node"><title>app/plug-in</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="128" cy="-981" rx="55.8614" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="128" y="-977.9" font-family="Times Roman,serif" font-size="14.00">app/plug-in</text>
|
||||
</g>
|
||||
<!-- app/composite -->
|
||||
<g id="node2" class="node"><title>app/composite</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="176" cy="-907" rx="67.8823" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="176" y="-903.9" font-family="Times Roman,serif" font-size="14.00">app/composite</text>
|
||||
</g>
|
||||
<!-- app/plug-in->app/composite -->
|
||||
<g id="edge2" class="edge"><title>app/plug-in->app/composite</title>
|
||||
<path fill="none" stroke="black" d="M140.112,-962.327C145.585,-953.891 152.16,-943.754 158.178,-934.475"/>
|
||||
<polygon fill="black" stroke="black" points="161.219,-936.219 163.724,-925.925 155.346,-932.41 161.219,-936.219"/>
|
||||
</g>
|
||||
<!-- app/base -->
|
||||
<g id="node4" class="node"><title>app/base</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="285" cy="-833" rx="44.7575" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="285" y="-829.9" font-family="Times Roman,serif" font-size="14.00">app/base</text>
|
||||
</g>
|
||||
<!-- app/composite->app/base -->
|
||||
<g id="edge4" class="edge"><title>app/composite->app/base</title>
|
||||
<path fill="none" stroke="black" d="M202.108,-889.275C217.2,-879.029 236.322,-866.047 252.396,-855.135"/>
|
||||
<polygon fill="black" stroke="black" points="254.66,-857.828 260.968,-849.315 250.728,-852.037 254.66,-857.828"/>
|
||||
</g>
|
||||
<!-- app/config -->
|
||||
<g id="node11" class="node"><title>app/config</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="311" cy="-759" rx="51.8276" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="311" y="-755.9" font-family="Times Roman,serif" font-size="14.00">app/config</text>
|
||||
</g>
|
||||
<!-- app/base->app/config -->
|
||||
<g id="edge10" class="edge"><title>app/base->app/config</title>
|
||||
<path fill="none" stroke="black" d="M291.696,-813.943C294.516,-805.916 297.859,-796.402 300.964,-787.565"/>
|
||||
<polygon fill="black" stroke="black" points="304.314,-788.587 304.327,-777.992 297.71,-786.267 304.314,-788.587"/>
|
||||
</g>
|
||||
<!-- libgimpcolor -->
|
||||
<g id="node6" class="node"><title>libgimpcolor</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="418" cy="-167" rx="61.0181" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="418" y="-163.9" font-family="Times Roman,serif" font-size="14.00">libgimpcolor</text>
|
||||
</g>
|
||||
<!-- libgimpmath -->
|
||||
<g id="node7" class="node"><title>libgimpmath</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="418" cy="-93" rx="61.0181" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="418" y="-89.9" font-family="Times Roman,serif" font-size="14.00">libgimpmath</text>
|
||||
</g>
|
||||
<!-- libgimpcolor->libgimpmath -->
|
||||
<g id="edge6" class="edge"><title>libgimpcolor->libgimpmath</title>
|
||||
<path fill="none" stroke="black" d="M418,-147.943C418,-140.149 418,-130.954 418,-122.338"/>
|
||||
<polygon fill="black" stroke="black" points="421.5,-122.249 418,-112.249 414.5,-122.249 421.5,-122.249"/>
|
||||
</g>
|
||||
<!-- GLib -->
|
||||
<g id="node9" class="node"><title>GLib</title>
|
||||
<ellipse fill="lightblue" stroke="black" cx="418" cy="-19" rx="31.8198" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="418" y="-15.9" font-family="Times Roman,serif" font-size="14.00">GLib</text>
|
||||
</g>
|
||||
<!-- libgimpmath->GLib -->
|
||||
<g id="edge8" class="edge"><title>libgimpmath->GLib</title>
|
||||
<path fill="none" stroke="black" d="M418,-73.9432C418,-66.1493 418,-56.9538 418,-48.3381"/>
|
||||
<polygon fill="black" stroke="black" points="421.5,-48.2494 418,-38.2495 414.5,-48.2495 421.5,-48.2494"/>
|
||||
</g>
|
||||
<!-- app/core -->
|
||||
<g id="node14" class="node"><title>app/core</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="336" cy="-685" rx="44.0472" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="336" y="-681.9" font-family="Times Roman,serif" font-size="14.00">app/core</text>
|
||||
</g>
|
||||
<!-- app/config->app/core -->
|
||||
<g id="edge26" class="edge"><title>app/config->app/core</title>
|
||||
<path fill="none" stroke="black" d="M317.438,-739.943C320.15,-731.916 323.364,-722.402 326.35,-713.565"/>
|
||||
<polygon fill="black" stroke="black" points="329.699,-714.586 329.584,-703.992 323.067,-712.346 329.699,-714.586"/>
|
||||
</g>
|
||||
<!-- GEGL -->
|
||||
<g id="node13" class="node"><title>GEGL</title>
|
||||
<ellipse fill="lightblue" stroke="black" cx="339" cy="-315" rx="36.977" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="339" y="-311.9" font-family="Times Roman,serif" font-size="14.00">GEGL</text>
|
||||
</g>
|
||||
<!-- app/pdb -->
|
||||
<g id="node15" class="node"><title>app/pdb</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="232" cy="-611" rx="41.9273" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="232" y="-607.9" font-family="Times Roman,serif" font-size="14.00">app/pdb</text>
|
||||
</g>
|
||||
<!-- app/core->app/pdb -->
|
||||
<g id="edge12" class="edge"><title>app/core->app/pdb</title>
|
||||
<path fill="none" stroke="black" d="M312.919,-668.577C298.276,-658.158 279.148,-644.548 263.166,-633.176"/>
|
||||
<polygon fill="black" stroke="black" points="264.836,-630.068 254.659,-627.122 260.777,-635.772 264.836,-630.068"/>
|
||||
</g>
|
||||
<!-- app/gegl -->
|
||||
<g id="node17" class="node"><title>app/gegl</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="336" cy="-611" rx="44.0472" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="336" y="-607.9" font-family="Times Roman,serif" font-size="14.00">app/gegl</text>
|
||||
</g>
|
||||
<!-- app/core->app/gegl -->
|
||||
<g id="edge14" class="edge"><title>app/core->app/gegl</title>
|
||||
<path fill="none" stroke="black" d="M330.012,-665.943C329.288,-658.088 329.08,-648.81 329.387,-640.136"/>
|
||||
<polygon fill="black" stroke="black" points="332.891,-640.19 330.018,-629.992 325.904,-639.756 332.891,-640.19"/>
|
||||
</g>
|
||||
<!-- app/xcf -->
|
||||
<g id="node19" class="node"><title>app/xcf</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="438" cy="-611" rx="39.8075" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="438" y="-607.9" font-family="Times Roman,serif" font-size="14.00">app/xcf</text>
|
||||
</g>
|
||||
<!-- app/core->app/xcf -->
|
||||
<g id="edge16" class="edge"><title>app/core->app/xcf</title>
|
||||
<path fill="none" stroke="black" d="M358.637,-668.577C372.998,-658.158 391.759,-644.548 407.434,-633.176"/>
|
||||
<polygon fill="black" stroke="black" points="409.738,-635.828 415.777,-627.122 405.628,-630.162 409.738,-635.828"/>
|
||||
</g>
|
||||
<!-- app/file -->
|
||||
<g id="node21" class="node"><title>app/file</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="80" cy="-537" rx="41.0122" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="80" y="-533.9" font-family="Times Roman,serif" font-size="14.00">app/file</text>
|
||||
</g>
|
||||
<!-- app/pdb->app/file -->
|
||||
<g id="edge18" class="edge"><title>app/pdb->app/file</title>
|
||||
<path fill="none" stroke="black" d="M203.41,-597.081C179.101,-585.246 144.017,-568.166 117.466,-555.24"/>
|
||||
<polygon fill="black" stroke="black" points="118.985,-552.087 108.462,-550.856 115.921,-558.381 118.985,-552.087"/>
|
||||
</g>
|
||||
<!-- libgimpmodule -->
|
||||
<g id="node23" class="node"><title>libgimpmodule</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="413" cy="-537" rx="70.9184" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="413" y="-533.9" font-family="Times Roman,serif" font-size="14.00">libgimpmodule</text>
|
||||
</g>
|
||||
<!-- app/pdb->libgimpmodule -->
|
||||
<g id="edge20" class="edge"><title>app/pdb->libgimpmodule</title>
|
||||
<path fill="none" stroke="black" d="M263.528,-598.11C291.34,-586.739 332.313,-569.988 364.331,-556.898"/>
|
||||
<polygon fill="black" stroke="black" points="366.024,-559.987 373.955,-552.963 363.375,-553.508 366.024,-559.987"/>
|
||||
</g>
|
||||
<!-- app/gegl->app/core -->
|
||||
<g id="edge22" class="edge"><title>app/gegl->app/core</title>
|
||||
<path fill="none" stroke="black" d="M341.982,-629.992C342.709,-637.839 342.92,-647.115 342.615,-655.792"/>
|
||||
<polygon fill="black" stroke="black" points="339.111,-655.746 341.988,-665.943 346.098,-656.178 339.111,-655.746"/>
|
||||
</g>
|
||||
<!-- app/text -->
|
||||
<g id="node26" class="node"><title>app/text</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="282" cy="-537" rx="41.9273" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="282" y="-533.9" font-family="Times Roman,serif" font-size="14.00">app/text</text>
|
||||
</g>
|
||||
<!-- app/xcf->app/text -->
|
||||
<g id="edge24" class="edge"><title>app/xcf->app/text</title>
|
||||
<path fill="none" stroke="black" d="M409.387,-597.427C384.444,-585.595 348.056,-568.334 320.55,-555.287"/>
|
||||
<polygon fill="black" stroke="black" points="321.76,-551.987 311.225,-550.863 318.76,-558.311 321.76,-551.987"/>
|
||||
</g>
|
||||
<!-- app/file->app/plug-in -->
|
||||
<g id="edge32" class="edge"><title>app/file->app/plug-in</title>
|
||||
<path fill="none" stroke="black" d="M80,-556.158C80,-584.37 80,-638.75 80,-685 80,-833 80,-833 80,-833 80,-875.187 84.7969,-886.276 99,-926 102.309,-935.256 106.934,-944.886 111.519,-953.453"/>
|
||||
<polygon fill="black" stroke="black" points="108.498,-955.223 116.415,-962.264 114.617,-951.823 108.498,-955.223"/>
|
||||
</g>
|
||||
<!-- libgimpthumb -->
|
||||
<g id="node34" class="node"><title>libgimpthumb</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="67" cy="-389" rx="67.1751" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="67" y="-385.9" font-family="Times Roman,serif" font-size="14.00">libgimpthumb</text>
|
||||
</g>
|
||||
<!-- app/file->libgimpthumb -->
|
||||
<g id="edge34" class="edge"><title>app/file->libgimpthumb</title>
|
||||
<path fill="none" stroke="black" d="M78.3271,-517.955C76.1162,-492.784 72.1982,-448.18 69.5998,-418.598"/>
|
||||
<polygon fill="black" stroke="black" points="73.0694,-418.098 68.7078,-408.442 66.0963,-418.71 73.0694,-418.098"/>
|
||||
</g>
|
||||
<!-- libgimpbase -->
|
||||
<g id="node29" class="node"><title>libgimpbase</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="418" cy="-241" rx="58.1882" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="418" y="-237.9" font-family="Times Roman,serif" font-size="14.00">libgimpbase</text>
|
||||
</g>
|
||||
<!-- libgimpmodule->libgimpbase -->
|
||||
<g id="edge36" class="edge"><title>libgimpmodule->libgimpbase</title>
|
||||
<path fill="none" stroke="black" d="M413.328,-517.579C414.183,-466.967 416.483,-330.777 417.503,-270.452"/>
|
||||
<polygon fill="black" stroke="black" points="421.008,-270.166 417.677,-260.108 414.009,-270.048 421.008,-270.166"/>
|
||||
</g>
|
||||
<!-- app/vectors -->
|
||||
<g id="node56" class="node"><title>app/vectors</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="334" cy="-463" rx="55.8614" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="334" y="-459.9" font-family="Times Roman,serif" font-size="14.00">app/vectors</text>
|
||||
</g>
|
||||
<!-- app/text->app/vectors -->
|
||||
<g id="edge76" class="edge"><title>app/text->app/vectors</title>
|
||||
<path fill="none" stroke="black" d="M294.854,-518.708C300.933,-510.057 308.313,-499.554 315.02,-490.01"/>
|
||||
<polygon fill="black" stroke="black" points="318.047,-491.79 320.933,-481.596 312.32,-487.765 318.047,-491.79"/>
|
||||
</g>
|
||||
<!-- Pango -->
|
||||
<g id="node70" class="node"><title>Pango</title>
|
||||
<ellipse fill="lightblue" stroke="black" cx="225" cy="-463" rx="34.8574" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="225" y="-459.9" font-family="Times Roman,serif" font-size="14.00">Pango</text>
|
||||
</g>
|
||||
<!-- app/text->Pango -->
|
||||
<g id="edge78" class="edge"><title>app/text->Pango</title>
|
||||
<path fill="none" stroke="black" d="M267.91,-518.708C260.905,-509.613 252.323,-498.471 244.679,-488.549"/>
|
||||
<polygon fill="black" stroke="black" points="247.41,-486.359 238.535,-480.572 241.865,-490.63 247.41,-486.359"/>
|
||||
</g>
|
||||
<!-- libgimpbase->libgimpcolor -->
|
||||
<g id="edge28" class="edge"><title>libgimpbase->libgimpcolor</title>
|
||||
<path fill="none" stroke="black" d="M418,-221.943C418,-214.149 418,-204.954 418,-196.338"/>
|
||||
<polygon fill="black" stroke="black" points="421.5,-196.249 418,-186.249 414.5,-196.249 421.5,-196.249"/>
|
||||
</g>
|
||||
<!-- libgimpconfig -->
|
||||
<g id="node31" class="node"><title>libgimpconfig</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="512" cy="-315" rx="65.9683" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="512" y="-311.9" font-family="Times Roman,serif" font-size="14.00">libgimpconfig</text>
|
||||
</g>
|
||||
<!-- libgimpconfig->libgimpbase -->
|
||||
<g id="edge30" class="edge"><title>libgimpconfig->libgimpbase</title>
|
||||
<path fill="none" stroke="black" d="M489.245,-297.087C477.006,-287.452 461.747,-275.439 448.493,-265.005"/>
|
||||
<polygon fill="black" stroke="black" points="450.568,-262.184 440.545,-258.748 446.238,-267.684 450.568,-262.184"/>
|
||||
</g>
|
||||
<!-- libgimpthumb->libgimpbase -->
|
||||
<g id="edge38" class="edge"><title>libgimpthumb->libgimpbase</title>
|
||||
<path fill="none" stroke="black" d="M72.6671,-369.993C80.1177,-348.474 95.3615,-314.069 121,-296 157.281,-270.43 275.454,-254.627 351.346,-246.855"/>
|
||||
<polygon fill="black" stroke="black" points="352.16,-250.291 361.761,-245.811 351.462,-243.326 352.16,-250.291"/>
|
||||
</g>
|
||||
<!-- Cairo -->
|
||||
<g id="node38" class="node"><title>Cairo</title>
|
||||
<ellipse fill="lightblue" stroke="black" cx="241" cy="-389" rx="33.234" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="241" y="-385.9" font-family="Times Roman,serif" font-size="14.00">Cairo</text>
|
||||
</g>
|
||||
<!-- app/actions -->
|
||||
<g id="node39" class="node"><title>app/actions</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="799" cy="-315" rx="55.1543" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="799" y="-311.9" font-family="Times Roman,serif" font-size="14.00">app/actions</text>
|
||||
</g>
|
||||
<!-- app/dialogs -->
|
||||
<g id="node40" class="node"><title>app/dialogs</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="756" cy="-685" rx="55.8614" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="756" y="-681.9" font-family="Times Roman,serif" font-size="14.00">app/dialogs</text>
|
||||
</g>
|
||||
<!-- app/actions->app/dialogs -->
|
||||
<g id="edge40" class="edge"><title>app/actions->app/dialogs</title>
|
||||
<path fill="none" stroke="black" d="M807.896,-334.161C819.955,-361.932 840,-415.275 840,-463 840,-537 840,-537 840,-537 840,-581.164 827.852,-592.208 805,-630 798.654,-640.495 790.185,-650.846 782.075,-659.688"/>
|
||||
<polygon fill="black" stroke="black" points="779.448,-657.372 775.103,-667.035 784.526,-662.19 779.448,-657.372"/>
|
||||
</g>
|
||||
<!-- app/gui -->
|
||||
<g id="node42" class="node"><title>app/gui</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="756" cy="-611" rx="39.8075" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="756" y="-607.9" font-family="Times Roman,serif" font-size="14.00">app/gui</text>
|
||||
</g>
|
||||
<!-- app/dialogs->app/gui -->
|
||||
<g id="edge42" class="edge"><title>app/dialogs->app/gui</title>
|
||||
<path fill="none" stroke="black" d="M756,-665.943C756,-658.149 756,-648.954 756,-640.338"/>
|
||||
<polygon fill="black" stroke="black" points="759.5,-640.249 756,-630.249 752.5,-640.249 759.5,-640.249"/>
|
||||
</g>
|
||||
<!-- app/display -->
|
||||
<g id="node44" class="node"><title>app/display</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="756" cy="-537" rx="55.8614" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="756" y="-533.9" font-family="Times Roman,serif" font-size="14.00">app/display</text>
|
||||
</g>
|
||||
<!-- app/gui->app/display -->
|
||||
<g id="edge44" class="edge"><title>app/gui->app/display</title>
|
||||
<path fill="none" stroke="black" d="M756,-591.943C756,-584.149 756,-574.954 756,-566.338"/>
|
||||
<polygon fill="black" stroke="black" points="759.5,-566.249 756,-556.249 752.5,-566.249 759.5,-566.249"/>
|
||||
</g>
|
||||
<!-- app/widgets -->
|
||||
<g id="node50" class="node"><title>app/widgets</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="754" cy="-463" rx="57.9828" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="754" y="-459.9" font-family="Times Roman,serif" font-size="14.00">app/widgets</text>
|
||||
</g>
|
||||
<!-- app/display->app/widgets -->
|
||||
<g id="edge50" class="edge"><title>app/display->app/widgets</title>
|
||||
<path fill="none" stroke="black" d="M755.485,-517.943C755.274,-510.149 755.026,-500.954 754.793,-492.338"/>
|
||||
<polygon fill="black" stroke="black" points="758.289,-492.151 754.52,-482.249 751.292,-492.34 758.289,-492.151"/>
|
||||
</g>
|
||||
<!-- libgimpwidgets -->
|
||||
<g id="node46" class="node"><title>libgimpwidgets</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="573" cy="-537" rx="70.9184" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="573" y="-533.9" font-family="Times Roman,serif" font-size="14.00">libgimpwidgets</text>
|
||||
</g>
|
||||
<!-- libgimpwidgets->libgimpconfig -->
|
||||
<g id="edge46" class="edge"><title>libgimpwidgets->libgimpconfig</title>
|
||||
<path fill="none" stroke="black" d="M554.592,-518.249C545.949,-508.295 536.384,-495.374 531,-482 512.661,-436.447 510.223,-378.617 510.704,-344.337"/>
|
||||
<polygon fill="black" stroke="black" points="514.209,-344.16 510.947,-334.08 507.211,-343.994 514.209,-344.16"/>
|
||||
</g>
|
||||
<!-- GTK+ -->
|
||||
<g id="node48" class="node"><title>GTK+</title>
|
||||
<ellipse fill="lightblue" stroke="black" cx="577" cy="-463" rx="36.977" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="577" y="-459.9" font-family="Times Roman,serif" font-size="14.00">GTK</text>
|
||||
</g>
|
||||
<!-- libgimpwidgets->GTK+ -->
|
||||
<g id="edge48" class="edge"><title>libgimpwidgets->GTK+</title>
|
||||
<path fill="none" stroke="black" d="M574.03,-517.943C574.451,-510.149 574.948,-500.954 575.414,-492.338"/>
|
||||
<polygon fill="black" stroke="black" points="578.915,-492.424 575.959,-482.249 571.925,-492.046 578.915,-492.424"/>
|
||||
</g>
|
||||
<!-- app/menus -->
|
||||
<g id="node52" class="node"><title>app/menus</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="756" cy="-389" rx="53.2379" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="756" y="-385.9" font-family="Times Roman,serif" font-size="14.00">app/menus</text>
|
||||
</g>
|
||||
<!-- app/widgets->app/menus -->
|
||||
<g id="edge52" class="edge"><title>app/widgets->app/menus</title>
|
||||
<path fill="none" stroke="black" d="M754.515,-443.943C754.726,-436.149 754.974,-426.954 755.207,-418.338"/>
|
||||
<polygon fill="black" stroke="black" points="758.708,-418.34 755.48,-408.249 751.711,-418.151 758.708,-418.34"/>
|
||||
</g>
|
||||
<!-- app/tools -->
|
||||
<g id="node54" class="node"><title>app/tools</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="641" cy="-759" rx="46.1672" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="641" y="-755.9" font-family="Times Roman,serif" font-size="14.00">app/tools</text>
|
||||
</g>
|
||||
<!-- app/widgets->app/tools -->
|
||||
<g id="edge54" class="edge"><title>app/widgets->app/tools</title>
|
||||
<path fill="none" stroke="black" d="M727.313,-480.099C714.423,-489.715 699.864,-502.832 691,-518 651.098,-586.285 642.758,-681.803 641.199,-729.484"/>
|
||||
<polygon fill="black" stroke="black" points="637.694,-729.637 640.946,-739.72 644.692,-729.81 637.694,-729.637"/>
|
||||
</g>
|
||||
<!-- app/menus->app/actions -->
|
||||
<g id="edge66" class="edge"><title>app/menus->app/actions</title>
|
||||
<path fill="none" stroke="black" d="M766.851,-370.327C771.74,-361.913 777.611,-351.809 782.991,-342.55"/>
|
||||
<polygon fill="black" stroke="black" points="786.155,-344.072 788.153,-333.667 780.102,-340.555 786.155,-344.072"/>
|
||||
</g>
|
||||
<!-- app/tools->app/core -->
|
||||
<g id="edge68" class="edge"><title>app/tools->app/core</title>
|
||||
<path fill="none" stroke="black" d="M601.127,-749.326C545.412,-735.808 444.384,-711.296 384.418,-696.747"/>
|
||||
<polygon fill="black" stroke="black" points="384.983,-693.283 374.44,-694.326 383.333,-700.086 384.983,-693.283"/>
|
||||
</g>
|
||||
<!-- app/tools->app/dialogs -->
|
||||
<g id="edge70" class="edge"><title>app/tools->app/dialogs</title>
|
||||
<path fill="none" stroke="black" d="M665.953,-742.943C682.076,-732.569 703.289,-718.918 721.076,-707.473"/>
|
||||
<polygon fill="black" stroke="black" points="722.979,-710.41 729.495,-702.055 719.191,-704.524 722.979,-710.41"/>
|
||||
</g>
|
||||
<!-- app/tools->libgimpwidgets -->
|
||||
<g id="edge72" class="edge"><title>app/tools->libgimpwidgets</title>
|
||||
<path fill="none" stroke="black" d="M638.418,-739.973C633.758,-708.448 622.562,-643.73 603,-592 599.525,-582.81 594.767,-573.258 590.065,-564.744"/>
|
||||
<polygon fill="black" stroke="black" points="593.052,-562.918 585.047,-555.978 586.977,-566.395 593.052,-562.918"/>
|
||||
</g>
|
||||
<!-- app/vectors->Cairo -->
|
||||
<g id="edge56" class="edge"><title>app/vectors->Cairo</title>
|
||||
<path fill="none" stroke="black" d="M311.96,-445.463C298.849,-435.031 282.111,-421.712 268.184,-410.63"/>
|
||||
<polygon fill="black" stroke="black" points="270.362,-407.891 260.358,-404.403 266.004,-413.368 270.362,-407.891"/>
|
||||
</g>
|
||||
<!-- app/paint -->
|
||||
<g id="node58" class="node"><title>app/paint</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="339" cy="-389" rx="46.8775" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="339" y="-385.9" font-family="Times Roman,serif" font-size="14.00">app/paint</text>
|
||||
</g>
|
||||
<!-- app/vectors->app/paint -->
|
||||
<g id="edge58" class="edge"><title>app/vectors->app/paint</title>
|
||||
<path fill="none" stroke="black" d="M335.288,-443.943C335.814,-436.149 336.436,-426.954 337.018,-418.338"/>
|
||||
<polygon fill="black" stroke="black" points="340.517,-418.463 337.699,-408.249 333.533,-417.991 340.517,-418.463"/>
|
||||
</g>
|
||||
<!-- app/paint->GEGL -->
|
||||
<g id="edge60" class="edge"><title>app/paint->GEGL</title>
|
||||
<path fill="none" stroke="black" d="M339,-369.943C339,-362.149 339,-352.954 339,-344.338"/>
|
||||
<polygon fill="black" stroke="black" points="342.5,-344.249 339,-334.249 335.5,-344.249 342.5,-344.249"/>
|
||||
</g>
|
||||
<!-- app/paint->libgimpconfig -->
|
||||
<g id="edge62" class="edge"><title>app/paint->libgimpconfig</title>
|
||||
<path fill="none" stroke="black" d="M371.54,-375.081C398.124,-363.71 436.03,-347.496 465.765,-334.777"/>
|
||||
<polygon fill="black" stroke="black" points="467.29,-337.931 475.108,-330.781 464.537,-331.495 467.29,-337.931"/>
|
||||
</g>
|
||||
<!-- app/paint-funcs -->
|
||||
<g id="node62" class="node"><title>app/paint-funcs</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="201" cy="-315" rx="70.9184" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="201" y="-311.9" font-family="Times Roman,serif" font-size="14.00">app/paint-funcs</text>
|
||||
</g>
|
||||
<!-- app/paint->app/paint-funcs -->
|
||||
<g id="edge64" class="edge"><title>app/paint->app/paint-funcs</title>
|
||||
<path fill="none" stroke="black" d="M310.406,-373.667C290.562,-363.026 263.832,-348.692 241.761,-336.857"/>
|
||||
<polygon fill="black" stroke="black" points="243.401,-333.765 232.934,-332.124 240.092,-339.934 243.401,-333.765"/>
|
||||
</g>
|
||||
<!-- app/paint-funcs->app/composite -->
|
||||
<g id="edge74" class="edge"><title>app/paint-funcs->app/composite</title>
|
||||
<path fill="none" stroke="black" d="M192.538,-334.205C181.067,-362.03 162,-415.437 162,-463 162,-759 162,-759 162,-759 162,-800.375 167.49,-847.969 171.594,-877.768"/>
|
||||
<polygon fill="black" stroke="black" points="168.161,-878.487 173.031,-887.896 175.092,-877.504 168.161,-878.487"/>
|
||||
</g>
|
||||
<!-- libgimp -->
|
||||
<g id="node72" class="node"><title>libgimp</title>
|
||||
<ellipse fill="#ff7256" stroke="black" cx="553" cy="-611" rx="41.2167" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="553" y="-607.9" font-family="Times Roman,serif" font-size="14.00">libgimp</text>
|
||||
</g>
|
||||
<!-- libgimp->libgimpmodule -->
|
||||
<g id="edge80" class="edge"><title>libgimp->libgimpmodule</title>
|
||||
<path fill="none" stroke="black" d="M525.674,-596.556C505.302,-585.788 477.131,-570.898 454.054,-558.7"/>
|
||||
<polygon fill="black" stroke="black" points="455.641,-555.58 445.164,-554.001 452.369,-561.768 455.641,-555.58"/>
|
||||
</g>
|
||||
<!-- libgimp->libgimpwidgets -->
|
||||
<g id="edge82" class="edge"><title>libgimp->libgimpwidgets</title>
|
||||
<path fill="none" stroke="black" d="M558.15,-591.943C560.297,-584.002 562.836,-574.606 565.203,-565.851"/>
|
||||
<polygon fill="black" stroke="black" points="568.637,-566.559 567.867,-555.992 561.879,-564.733 568.637,-566.559"/>
|
||||
</g>
|
||||
<!-- app/tests -->
|
||||
<g id="node75" class="node"><title>app/tests</title>
|
||||
<ellipse fill="lawngreen" stroke="black" cx="756" cy="-759" rx="44.7575" ry="19.0919"/>
|
||||
<text text-anchor="middle" x="756" y="-755.9" font-family="Times Roman,serif" font-size="14.00">app/tests</text>
|
||||
</g>
|
||||
<!-- app/tests->app/dialogs -->
|
||||
<g id="edge84" class="edge"><title>app/tests->app/dialogs</title>
|
||||
<path fill="none" stroke="black" d="M756,-739.943C756,-732.149 756,-722.954 756,-714.338"/>
|
||||
<polygon fill="black" stroke="black" points="759.5,-714.249 756,-704.249 752.5,-714.249 759.5,-714.249"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 24 KiB |
2
devel-docs/reference/meson.build
Normal file
@ -0,0 +1,2 @@
|
||||
subdir('pika')
|
||||
subdir('pika-ui')
|
BIN
devel-docs/reference/pika-ui/images/browser.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
devel-docs/reference/pika-ui/images/busy-box.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
devel-docs/reference/pika-ui/images/button.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
devel-docs/reference/pika-ui/images/chain-button.png
Normal file
After Width: | Height: | Size: 4.8 KiB |
BIN
devel-docs/reference/pika-ui/images/color-area.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
devel-docs/reference/pika-ui/images/color-button.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
devel-docs/reference/pika-ui/images/color-hex-entry.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
devel-docs/reference/pika-ui/images/color-notebook.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
devel-docs/reference/pika-ui/images/color-profile-combo-box.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
devel-docs/reference/pika-ui/images/color-profile-view.png
Normal file
After Width: | Height: | Size: 7.1 KiB |
BIN
devel-docs/reference/pika-ui/images/color-scale.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
devel-docs/reference/pika-ui/images/color-scales.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
devel-docs/reference/pika-ui/images/color-select.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
devel-docs/reference/pika-ui/images/color-selection.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
devel-docs/reference/pika-ui/images/dialog.png
Normal file
After Width: | Height: | Size: 7.7 KiB |
BIN
devel-docs/reference/pika-ui/images/enum-combo-box.png
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
devel-docs/reference/pika-ui/images/enum-label.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
devel-docs/reference/pika-ui/images/file-entry.png
Normal file
After Width: | Height: | Size: 4.1 KiB |
BIN
devel-docs/reference/pika-ui/images/frame.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
devel-docs/reference/pika-ui/images/hint-box.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
devel-docs/reference/pika-ui/images/int-combo-box.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
devel-docs/reference/pika-ui/images/memsize-entry.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
devel-docs/reference/pika-ui/images/number-pair-entry.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
devel-docs/reference/pika-ui/images/offset-area.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
devel-docs/reference/pika-ui/images/page-selector.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
devel-docs/reference/pika-ui/images/path-editor.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
devel-docs/reference/pika-ui/images/pick-button.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
devel-docs/reference/pika-ui/images/preview-area.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
devel-docs/reference/pika-ui/images/ruler.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
devel-docs/reference/pika-ui/images/string-combo-box.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
devel-docs/reference/pika-ui/images/unit-combo-box.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
39
devel-docs/reference/pika-ui/meson.build
Normal file
@ -0,0 +1,39 @@
|
||||
# Extra markdown files
|
||||
pika_ui_doc_content_files = [
|
||||
'widget-gallery.md',
|
||||
]
|
||||
|
||||
pika_ui_doc_toml = configure_file(
|
||||
input: 'pika-ui-3.0.toml.in',
|
||||
output: '@BASENAME@',
|
||||
configuration: {
|
||||
'PIKA_VERSION': pika_version,
|
||||
'PIKA_LOGO': '../images/' + (stable ? 'pika-logo.png' : 'pika-devel-logo.png'),
|
||||
},
|
||||
)
|
||||
|
||||
pika_ui_docs = custom_target('pika-ui-docs',
|
||||
input: libpikaui_gir[0],
|
||||
output: 'libpikaui-@0@'.format(pika_api_version),
|
||||
command: [
|
||||
gi_docgen,
|
||||
'generate',
|
||||
'--quiet',
|
||||
'--fatal-warnings',
|
||||
'--config', pika_ui_doc_toml,
|
||||
'--output-dir=@OUTPUT@',
|
||||
'--no-namespace-dir',
|
||||
'--content-dir=@0@'.format(meson.current_source_dir()),
|
||||
'--add-include-path=@0@'.format(meson.project_build_root() / 'libpika'),
|
||||
'--add-include-path=@0@'.format(get_option('prefix') / 'share' / 'gir-1.0'),
|
||||
'@INPUT@',
|
||||
],
|
||||
depends: libpika_gir[0],
|
||||
depend_files: [
|
||||
pika_ui_doc_toml,
|
||||
pika_ui_doc_content_files,
|
||||
],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: get_option('datadir') / 'doc' / 'pika-@0@'.format(pika_app_version),
|
||||
)
|
119
devel-docs/reference/pika-ui/pika-ui-3.0.toml.in
Normal file
@ -0,0 +1,119 @@
|
||||
[library]
|
||||
namespace = "PikaUi"
|
||||
version = "@PIKA_VERSION@"
|
||||
browse_url = "https://gitlab.gnome.org/GNOME/pika/"
|
||||
repository_url = "https://gitlab.gnome.org/GNOME/pika.git"
|
||||
website_url = "https://heckin.technology/AlderconeStudio/PIKApp"
|
||||
authors = "PIKA contributors"
|
||||
logo_url = "@PIKA_LOGO@"
|
||||
license = "GPL-3.0-or-later"
|
||||
description = "PIKA UI library"
|
||||
dependencies = [
|
||||
'Babl-0.1',
|
||||
'Pika-3.0',
|
||||
'GLib-2.0',
|
||||
'GObject-2.0',
|
||||
'GdkPixbuf-2.0',
|
||||
'Gegl-0.4',
|
||||
'Gio-2.0',
|
||||
'Gtk-3.0',
|
||||
'cairo-1.0',
|
||||
]
|
||||
devhelp = true
|
||||
search_index = true
|
||||
|
||||
# These links are mostly used for the dependency lists in index page.
|
||||
|
||||
[dependencies."Babl-0.1"]
|
||||
name = "Babl"
|
||||
description = "Pixel encoding and color space conversion engine"
|
||||
docs_url = "https://gegl.org/babl"
|
||||
|
||||
[dependencies."Pika-3.0"]
|
||||
name = "Pika"
|
||||
description = "PIKA Library"
|
||||
docs_url = "https://developer.pika.org/api/3.0/libpika/"
|
||||
|
||||
[dependencies."GLib-2.0"]
|
||||
name = "GLib"
|
||||
description = "C Utility Library"
|
||||
docs_url = "https://developer.gnome.org/glib/stable"
|
||||
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[dependencies."GdkPixbuf-2.0"]
|
||||
name = "GdkPixbuf"
|
||||
description = "Image loading and scaling"
|
||||
docs_url = "https://docs.gtk.org/gdk-pixbuf/"
|
||||
|
||||
[dependencies."Gegl-0.4"]
|
||||
name = "Gegl"
|
||||
description = "Generic Graphics Library"
|
||||
docs_url = "https://gegl.org/"
|
||||
|
||||
[dependencies."Gio-2.0"]
|
||||
name = "Gio"
|
||||
description = "GObject interfaces and objects"
|
||||
docs_url = "https://developer.gnome.org/gio/stable"
|
||||
|
||||
[dependencies."Gtk-3.0"]
|
||||
name = "Gtk"
|
||||
description = "The GTK toolkit"
|
||||
docs_url = "https://developer.gnome.org/gtk3/stable"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "cairo"
|
||||
description = "A 2D graphics library with support for multiple output devices"
|
||||
docs_url = "https://www.cairographics.org/manual/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
show_index_summary = true
|
||||
show_class_hierarchy = true
|
||||
|
||||
[source-location]
|
||||
base_url = "https://gitlab.gnome.org/GNOME/pika/-/blob/master/"
|
||||
|
||||
[extra]
|
||||
content_files = [
|
||||
'widget-gallery.md',
|
||||
]
|
||||
content_images = [
|
||||
'images/browser.png',
|
||||
'images/busy-box.png',
|
||||
'images/button.png',
|
||||
'images/chain-button.png',
|
||||
'images/color-area.png',
|
||||
'images/color-button.png',
|
||||
'images/color-hex-entry.png',
|
||||
'images/color-notebook.png',
|
||||
'images/color-profile-combo-box.png',
|
||||
'images/color-profile-view.png',
|
||||
'images/color-scale.png',
|
||||
'images/color-scales.png',
|
||||
'images/color-select.png',
|
||||
'images/color-selection.png',
|
||||
'images/dialog.png',
|
||||
'images/enum-combo-box.png',
|
||||
'images/enum-label.png',
|
||||
'images/file-entry.png',
|
||||
'images/frame.png',
|
||||
'images/hint-box.png',
|
||||
'images/int-combo-box.png',
|
||||
'images/memsize-entry.png',
|
||||
'images/number-pair-entry.png',
|
||||
'images/offset-area.png',
|
||||
'images/page-selector.png',
|
||||
'images/path-editor.png',
|
||||
'images/pick-button.png',
|
||||
'images/preview-area.png',
|
||||
'images/ruler.png',
|
||||
'images/string-combo-box.png',
|
||||
'images/unit-combo-box.png',
|
||||
]
|
||||
# The urlmap is used as base links when an API docs refer to a type or
|
||||
# function from another library.
|
||||
urlmap_file = "urlmap.js"
|
12
devel-docs/reference/pika-ui/urlmap.js
Normal file
@ -0,0 +1,12 @@
|
||||
// A map between namespaces and base URLs for their online gi-docgen documentation
|
||||
baseURLs = [
|
||||
[ 'Babl', 'https://developer.pika.org/api/babl/' ],
|
||||
[ 'Gegl', 'https://developer.pika.org/api/gegl/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk3/' ],
|
||||
[ 'GdkPixbuf', 'https://docs.gtk.org/gdk-pixbuf/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk3/' ],
|
||||
[ 'Pika', 'https://developer.pika.org/api/3.0/libpika/' ],
|
||||
]
|
36
devel-docs/reference/pika-ui/widget-gallery.md
Normal file
@ -0,0 +1,36 @@
|
||||
Title: Widget gallery
|
||||
|
||||
Widget gallery
|
||||
==============
|
||||
|
||||
[](class.Browser.html)
|
||||
[](class.Button.html)
|
||||
[](class.BusyBox.html)
|
||||
[](class.ChainButton.html)
|
||||
[](class.ColorArea.html)
|
||||
[](class.ColorButton.html)
|
||||
[](class.ColorHexEntry.html)
|
||||
[](class.ColorNotebook.html)
|
||||
[](class.ColorScale.html)
|
||||
[](class.ColorScales.html)
|
||||
[](class.ColorSelect.html)
|
||||
[](class.ColorSelection.html)
|
||||
[](class.ColorProfileComboBox.html)
|
||||
[](class.ColorProfileView.html)
|
||||
[](class.Dialog.html)
|
||||
[](class.EnumComboBox.html)
|
||||
[](class.EnumLabel.html)
|
||||
[](class.FileEntry.html)
|
||||
[](class.Frame.html)
|
||||
[](class.HintBox.html)
|
||||
[](class.IntComboBox.html)
|
||||
[](class.MemsizeEntry.html)
|
||||
[](class.NumberPairEntry.html)
|
||||
[](class.OffsetArea.html)
|
||||
[](class.PageSelector.html)
|
||||
[](class.PathEditor.html)
|
||||
[](class.PickButton.html)
|
||||
[](class.PreviewArea.html)
|
||||
[](class.Ruler.html)
|
||||
[](class.StringComboBox.html)
|
||||
[](class.UnitComboBox.html)
|
36
devel-docs/reference/pika/meson.build
Normal file
@ -0,0 +1,36 @@
|
||||
# Extra markdown files
|
||||
pika_doc_content_files = [
|
||||
]
|
||||
|
||||
pika_doc_toml = configure_file(
|
||||
input: 'pika-3.0.toml.in',
|
||||
output: '@BASENAME@',
|
||||
configuration: {
|
||||
'PIKA_VERSION': pika_version,
|
||||
'PIKA_LOGO_PATH': '../images/' + (stable ? 'pika-logo.png' : 'pika-devel-logo.png'),
|
||||
},
|
||||
)
|
||||
|
||||
pika_docs = custom_target('pika-docs',
|
||||
input: libpika_gir[0],
|
||||
output: 'libpika-@0@'.format(pika_api_version),
|
||||
command: [
|
||||
gi_docgen,
|
||||
'generate',
|
||||
'--quiet',
|
||||
'--fatal-warnings',
|
||||
'--config', pika_doc_toml,
|
||||
'--output-dir=@OUTPUT@',
|
||||
'--no-namespace-dir',
|
||||
'--content-dir=@0@'.format(meson.current_source_dir()),
|
||||
'--add-include-path=@0@'.format(get_option('prefix') / 'share' / 'gir-1.0'),
|
||||
'@INPUT@',
|
||||
],
|
||||
depend_files: [
|
||||
pika_doc_toml,
|
||||
pika_doc_content_files,
|
||||
],
|
||||
build_by_default: true,
|
||||
install: true,
|
||||
install_dir: get_option('datadir') / 'doc' / 'pika-@0@'.format(pika_app_version),
|
||||
)
|
75
devel-docs/reference/pika/pika-3.0.toml.in
Normal file
@ -0,0 +1,75 @@
|
||||
[library]
|
||||
namespace = "Pika"
|
||||
version = "@PIKA_VERSION@"
|
||||
browse_url = "https://gitlab.gnome.org/GNOME/pika/"
|
||||
repository_url = "https://gitlab.gnome.org/GNOME/pika.git"
|
||||
website_url = "https://heckin.technology/AlderconeStudio/PIKApp"
|
||||
authors = "PIKA contributors"
|
||||
logo_url = "@PIKA_LOGO_PATH@"
|
||||
license = "GPL-3.0-or-later"
|
||||
description = "PIKA library"
|
||||
dependencies = [
|
||||
'Babl-0.1',
|
||||
'GLib-2.0',
|
||||
'GObject-2.0',
|
||||
'GdkPixbuf-2.0',
|
||||
'Gegl-0.4',
|
||||
'Gio-2.0',
|
||||
'Gtk-3.0',
|
||||
'cairo-1.0',
|
||||
]
|
||||
devhelp = true
|
||||
search_index = true
|
||||
|
||||
[dependencies."Babl-0.1"]
|
||||
name = "Babl"
|
||||
description = "Pixel encoding and color space conversion engine"
|
||||
docs_url = "https://gegl.org/babl"
|
||||
|
||||
[dependencies."GLib-2.0"]
|
||||
name = "GLib"
|
||||
description = "C Utility Library"
|
||||
docs_url = "https://developer.gnome.org/glib/stable"
|
||||
|
||||
[dependencies."GObject-2.0"]
|
||||
name = "GObject"
|
||||
description = "The base type system library"
|
||||
docs_url = "https://developer.gnome.org/gobject/stable"
|
||||
|
||||
[dependencies."GdkPixbuf-2.0"]
|
||||
name = "GdkPixbuf"
|
||||
description = "Image loading and scaling"
|
||||
docs_url = "https://docs.gtk.org/gdk-pixbuf/"
|
||||
|
||||
[dependencies."Gegl-0.4"]
|
||||
name = "Gegl"
|
||||
description = "Generic Graphics Library"
|
||||
docs_url = "https://gegl.org/"
|
||||
|
||||
[dependencies."Gio-2.0"]
|
||||
name = "Gio"
|
||||
description = "GObject interfaces and objects"
|
||||
docs_url = "https://developer.gnome.org/gio/stable"
|
||||
|
||||
[dependencies."Gtk-3.0"]
|
||||
name = "Gtk"
|
||||
description = "The GTK toolkit"
|
||||
docs_url = "https://developer.gnome.org/gtk3/stable"
|
||||
|
||||
[dependencies."cairo-1.0"]
|
||||
name = "cairo"
|
||||
description = "A 2D graphics library with support for multiple output devices"
|
||||
docs_url = "https://www.cairographics.org/manual/"
|
||||
|
||||
[theme]
|
||||
name = "basic"
|
||||
show_index_summary = true
|
||||
show_class_hierarchy = true
|
||||
|
||||
[source-location]
|
||||
base_url = "https://gitlab.gnome.org/GNOME/pika/-/blob/master/"
|
||||
|
||||
[extra]
|
||||
content_files = [
|
||||
]
|
||||
urlmap_file = "urlmap.js"
|
11
devel-docs/reference/pika/urlmap.js
Normal file
@ -0,0 +1,11 @@
|
||||
// A map between namespaces and base URLs for their online gi-docgen documentation
|
||||
baseURLs = [
|
||||
[ 'Babl', 'https://developer.pika.org/api/babl/' ],
|
||||
[ 'Gegl', 'https://developer.pika.org/api/gegl/' ],
|
||||
[ 'GLib', 'https://docs.gtk.org/glib/' ],
|
||||
[ 'GObject', 'https://docs.gtk.org/gobject/' ],
|
||||
[ 'Gdk', 'https://docs.gtk.org/gdk3/' ],
|
||||
[ 'GdkPixbuf', 'https://docs.gtk.org/gdk-pixbuf/' ],
|
||||
[ 'Gio', 'https://docs.gtk.org/gio/' ],
|
||||
[ 'Gtk', 'https://docs.gtk.org/gtk3/' ],
|
||||
]
|
148
devel-docs/tagging.txt
Normal file
@ -0,0 +1,148 @@
|
||||
=============================================================
|
||||
How does resource tagging in Pika work?
|
||||
=============================================================
|
||||
|
||||
|
||||
PikaTagged
|
||||
|
||||
Tagging is not limited to a concrete class hierarchy, but any class
|
||||
implementing the PikaTagged interface can be tagged. In addition to
|
||||
methods for adding/removing/enumerating tags it also requires
|
||||
PikaTagged objects to identify themselves:
|
||||
|
||||
* pika_tagged_get_identifier: used to get a unique identifier of a
|
||||
PikaTagged object. For objects which are stored in a file it will
|
||||
usually be a filename.
|
||||
|
||||
* pika_tagged_get_checksum: the identifier mentioned above has the problem
|
||||
that it can change during sessions (for example, user moves or renames
|
||||
a resource file). Therefore, there needs to be a way to get another
|
||||
identifier from the data of the tagged object, so that tags stored between
|
||||
session can be remapped properly.
|
||||
|
||||
|
||||
PikaTag
|
||||
|
||||
Tags are represented by a PikaTag object. There are no limitations for
|
||||
tag names except that they cannot contain a selected set of terminal
|
||||
punctuation characters (used to separate tags), leading or trailing
|
||||
whitespace and cannot begin with a reserved prefix for internal tags
|
||||
('pika:'). These conditions are enforced when creating a tag object from a
|
||||
tag string. The only reason for tag creation to fail is if there are
|
||||
no characters left after trying to fix a tag according to the
|
||||
rules above. Tag names are displayed as the user typed them (case
|
||||
sensitive), but tag comparison is done case-insensitively.
|
||||
|
||||
Tags are immutable, i.e. when a tag is created with one name string, it
|
||||
cannot be changed, but a new tag has to be created instead.
|
||||
|
||||
There are methods provided for convenient use with glib, a comparison
|
||||
function which can be used to sort tag lists and functions for storing
|
||||
tags in a GHashTable.
|
||||
|
||||
|
||||
PikaTagCache
|
||||
|
||||
Between sessions, tags assigned to objects are stored in a cache
|
||||
file. The cache file is a simple XML file, which lists all resources and
|
||||
tags which are added to them. Resources which have no tags assigned
|
||||
are listed here too, so that when we check the cache we know that they
|
||||
have no tags assigned instead of trying to find out if the resource file
|
||||
has been renamed.
|
||||
|
||||
When the session ends, a list of all resources and their tags
|
||||
is constructed. Resources which were not loaded during this session,
|
||||
but had tags assigned are also added to the list (they are saved
|
||||
because they could be useful in the next session, for example, when
|
||||
a temporarily disconnected network directory is reconnected). The list
|
||||
is then written to a tag cache file in the user's home directory.
|
||||
|
||||
When the session starts, the previously saved resource and tag mapping has to
|
||||
be loaded and assigned to PikaTagged objects. First the tag cache is
|
||||
loaded from file, and then containers are added (PikaContainer objects
|
||||
which contain items implementing the PikaTagged interface). After that,
|
||||
loaded resources are assigned tags:
|
||||
|
||||
If a resource identifier matches an identifier in the cache,
|
||||
corresponding tags are assigned to the PikaTagged object.
|
||||
Else, if the identifier is not found in the tag cache,
|
||||
an attempt is made to check if the resource file has been
|
||||
moved/renamed. In such case the checksum is used to match the
|
||||
PikaTagged object with all of the records in the tag cache.
|
||||
If a match is found,
|
||||
the identifier is updated in the tag cache.
|
||||
Otherwise,
|
||||
the loaded PikaTagged object is considered to be a newly
|
||||
added resource.
|
||||
|
||||
|
||||
PikaFilteredContainer
|
||||
|
||||
A PikaFilteredContainer is a "view" (representation) of a
|
||||
PikaContainer. It is related to tagging in that it can be used to
|
||||
filter a PikaContainer to contain only PikaTagged objects which have
|
||||
certain tags assigned. It is automatically updated with any changes in
|
||||
the PikaContainer it wraps. However, items should not be added or removed
|
||||
from this container manually as changes do not affect the original
|
||||
container and would be lost when the PikaFilteredContainer is
|
||||
updated. Instead, the contents should be changed by setting a tag list
|
||||
which would be used to filter PikaTagged objects containing all of the
|
||||
given PikaTags.
|
||||
|
||||
PikaFilteredContainer can use any PikaContainer as a source
|
||||
container. Therefore, it is possible to use the decorator design pattern
|
||||
to implement additional container views, such as a view combining items
|
||||
from multiple containers.
|
||||
|
||||
|
||||
PikaTagEntry widget
|
||||
|
||||
The PikaTagEntry widget extends GtkEntry and is used to either assign or
|
||||
query tags depending on the selected mode. The widget support various
|
||||
usability features:
|
||||
|
||||
* Jellybeans: When a tag is entered and confirmed by either separator,
|
||||
pressing return or otherwise, it becomes a jellybean, i.e. a single
|
||||
unit, not a bunch of characters. Navigating in a PikaTagEntry,
|
||||
deleting tags, etc. can be performed much faster. However, while a tag
|
||||
is just being entered (not yet confirmed), all actions operate on
|
||||
characters as usual.
|
||||
|
||||
* Custom auto completion is implemented in the PikaTagEntry widget which
|
||||
allows to complete tags in the middle of a tag list, doesn't offer
|
||||
already completed tags, tab cycles all possible completions, etc.
|
||||
|
||||
* If the PikaTagEntry is empty and unused it displays a description for
|
||||
the user regarding its purpose.
|
||||
|
||||
When operating in tag assignment mode, tags are assigned only when
|
||||
the user hits the return key.
|
||||
|
||||
When operating in tag query mode, the given PikaFilteredContainer is
|
||||
filtered as the user types. The PikaTagEntry also remembers recently used
|
||||
configurations, which can be cycled using up and down arrow keys.
|
||||
|
||||
|
||||
PikaComboTagEntry widget
|
||||
|
||||
The PikaComboTagEntry widget extends PikaTagEntry and adds the ability to pick
|
||||
tags from a menu-like list (using the PikaTagPopup widget).
|
||||
|
||||
|
||||
PikaTagPopup widget
|
||||
|
||||
The PikaTagPopup widget is used as a tag list menu from the PikaComboTagEntry
|
||||
widget. It is not designed to be used with any other widget.
|
||||
|
||||
PikaTagPopup has many visual and behavioral similarities to GtkMenu.
|
||||
In particular, it uses menu-like scrolling.
|
||||
|
||||
PikaTagPopup implements various usability features, some of which are:
|
||||
|
||||
* Tags which would result in an empty selection of resources are made
|
||||
insensitive.
|
||||
|
||||
* Closing either with the keyboard or by clicking outside the popup area.
|
||||
|
||||
* Underlining of highlighted (hovered) tags.
|
||||
|
57
devel-docs/ui-framework.txt
Normal file
@ -0,0 +1,57 @@
|
||||
PIKA UI Framework
|
||||
=================
|
||||
|
||||
This document describes how the PIKA UI framework functions and is
|
||||
implemented. Here, "UI framework" refers to the system that saves the
|
||||
UI layout between PIKA sessions, i.e. how docks, dockable dialogs etc
|
||||
are setup.
|
||||
|
||||
|
||||
Key Classes
|
||||
-----------
|
||||
|
||||
PikaDockable - Represents a dockable dialog.
|
||||
PikaDockbook - A GtkNotebook of PikaDockables
|
||||
PikaDock - A columns of PikaDockbooks
|
||||
PikaToolbox - Subclasses PikaDock, contains the toolbox.
|
||||
Dockables are added at the bottom
|
||||
PikaMenuDock - Subclasses PikaDock, contains dockables, should
|
||||
probably be merged with PikaDock. The name
|
||||
contains "menu" from the time when it hosted the
|
||||
Image Selection Menu that is now in the
|
||||
PikaDockWindow
|
||||
PikaDockColumns - A set of PikaDocks arranged side by side.
|
||||
PikaDockWindow - A toplevel window containing a PikaDockColumns.
|
||||
PikaImageWindow - A toplevel window containing images and one
|
||||
PikaDockColumns to the left and to the right.
|
||||
PikaDialogFactory - A factory to create and position toplevel windows
|
||||
PikaSessionInfo - Contains session info for one toplevel
|
||||
PikaUIConfigurer - Configures the UI when switching between
|
||||
single-window and multi-window mode
|
||||
|
||||
|
||||
PikaDialogFactory
|
||||
-----------------
|
||||
|
||||
The PikaDialogFactory can be considered to solve two distinct
|
||||
problems:
|
||||
|
||||
1. Create widgets from text, in particular from text in sessionrc
|
||||
2. Session manage toplevel windows so their position is remembered
|
||||
across PIKA sessions
|
||||
|
||||
One possible design adjustment would be to have PikaWidgetFactory that
|
||||
takes care of 1), and then have PikaDialogFactory inherit from
|
||||
GtkWidgetFactory and implementing 2). PikaWidgetFactory could possibly
|
||||
use GtkBuilder.
|
||||
|
||||
|
||||
sessionrc
|
||||
---------
|
||||
When PIKA starts, the sessionrc file is parsed. This step puts
|
||||
PikaSessionInfo:s into PikaDialogFactories. Later when dialogs are
|
||||
created, the dialog factory looks up existing session info entries. If
|
||||
one exists, it uses the session info to set e.g. the position of the
|
||||
created dialog. If it doesn't exist, it creates a new session info
|
||||
object for the dialog. When PIKA exists, the current session infos are
|
||||
then written back to sessionrc.
|
73
devel-docs/undo.txt
Normal file
@ -0,0 +1,73 @@
|
||||
A quick overview of the undo system
|
||||
-----------------------------------
|
||||
|
||||
Actions on the image by the user are pushed onto an undo stack. Each
|
||||
action object includes all the information needed to undo or redo an
|
||||
operation, plus an UndoType. The type can be converted to text to
|
||||
show to the user. Actions may be run forwards (UndoState == REDO) or
|
||||
backwards (UndoState == UNDO). As the action is run, it swaps the
|
||||
image's current state and the recorded state. A run action is moved
|
||||
from the undo stack to the redo stack (or vice-versa if UndoState ==
|
||||
REDO). Pushing something onto the undo stack causes the redo stack to
|
||||
be cleared, since the actions on the redo stack may depend on the
|
||||
image being in a particular state (eg consider: layer add, rename,
|
||||
undo rename, layer delete. If the redo stack weren't cleared on undo,
|
||||
then there would still be a "rename" operation on the redo stack which
|
||||
could be run on a non-existent layer. Bad news.)
|
||||
|
||||
Undo groups
|
||||
-----------
|
||||
In order to group many basic operations together into a more useful
|
||||
whole, code can push group start and end markers. A group is treated
|
||||
as a single action for the purposes of the undo and redo user
|
||||
commands. It is legal to nest groups, in which case the outermost
|
||||
group is the only user-visible one.
|
||||
|
||||
Groups boundaries used to be implemented by pushing a NULL pointer on
|
||||
the undo (or redo) stack. Now they are a special action which has the
|
||||
"group_boundary" bit set. This allows the group boundaries to include
|
||||
the undo type associated with the whole group. The individual actions
|
||||
need to preserve their own undo type since the undo_free_* functions
|
||||
sometimes need to know which action is being freed.
|
||||
|
||||
Undo events
|
||||
-----------
|
||||
Images emit UNDO_EVENT signals, to say that the user has performed an
|
||||
undo or redo action on that image. This allows interested parties to
|
||||
track image mutation actions. So far, only the undo history dialog
|
||||
uses this feature. The other way to discover the undo status of an
|
||||
image is to use the iterator functions undo_map_over_undo_stack() and
|
||||
undo_map_over_redo_stack(). These call your function on each action
|
||||
(or group) on the stack. There is also undo_get_undo_name() and
|
||||
undo_get_redo_name() to peek at the top items on each stack. This
|
||||
could be used (eg) to change the undo/redo menu strings to something
|
||||
more meaningful, but currently lack synchronisation.
|
||||
|
||||
Dirtying images
|
||||
---------------
|
||||
NOTE about the gimage->dirty counter:
|
||||
If 0, then the image is clean (ie, copy on disk is the same as the one
|
||||
in memory).
|
||||
If positive, then that's the number of dirtying operations done
|
||||
on the image since the last save.
|
||||
If negative, then user has hit undo and gone back in time prior
|
||||
to the saved copy. Hitting redo will eventually come back to
|
||||
the saved copy.
|
||||
The image is dirty (ie, needs saving) if counter is non-zero.
|
||||
If the counter is around 10000, this is due to undo-ing back
|
||||
before a saved version, then mutating the image (thus destroying
|
||||
the redo stack). Once this has happened, it's impossible to get
|
||||
the image back to the state on disk, since the redo info has been
|
||||
freed. See undo.c for the gorey details.
|
||||
|
||||
NEVER CALL pika_image_dirty() directly!
|
||||
|
||||
If your code has just dirtied the image, push an undo instead.
|
||||
Failing that, push the trivial undo which tells the user the
|
||||
command is not undoable: undo_push_cantundo() (But really, it would
|
||||
be best to push a proper undo). If you just dirty the image
|
||||
without pushing an undo then the dirty count is increased, but
|
||||
popping that many undo actions won't lead to a clean image.
|
||||
|
||||
Austin
|
||||
|