devel-docs: delete various devel docs which are now in developer.gimp.org.

This commit is contained in:
Jehan 2022-10-15 22:29:03 +02:00
parent 6c0c2f15c4
commit 62963aa748
6 changed files with 11 additions and 1347 deletions

View File

@ -1,963 +0,0 @@
# GIMP Coding Style
This document describes the preferred coding style for the GIMP source code.
It was originally inspired by [GNU's coding
style](https://www.gnu.org/prep/standards/standards.html#Writing-C) and
developed from there across the years.
Coding style is completely arbitrary as it is a a matter of consistency,
readability and maintenance, not taste. Therefore it doesn't matter what
you prefer (we all have some part of the rules we would like different,
and we can apply these to our personal projects), just follow these
rules so that we can work together efficiently.
This document will use examples at the very least to provide
authoritative and consistent answers to common questions regarding the
coding style and will also try to identify the allowed exceptions.
## Table of contents
[TOC]
## Dealing with the old code
__The new GIMP code should adhere to the style explained below.__ The existing
GIMP code largely follows these conventions, but there are some differences like
extra or missing whitespace, tabs instead of space, wrong formatting, etc.
__Our policy is to update the style of a code block or function if and only if
you happen to touch that code.__
Please don't waste your time and reviewers' time with merge requests or patches
with _only_ code style fixes unless you have push rights to the GIMP's
repository.
## Git usage
### Commit messages
Commit messages should follow the following rules:
- Always provide informative titles. No one-word commits saying nothing
like "bug fix", so that we can at least search through the git history
if needed. It can still be short messages for very simple fixes: for
instance "Fix typo" or "Fix small memory leak" are informative of the
type of fix.
- Prefix the title with the codebase section (i.e. the root folder
usually) which was changed. For instance: `libgimpbase: fix memory
leak` immediately tells us it was a memory leak fix in the
`libgimpbase` library. If several sections are touched, list them with
comma-separation.
- Alternatively, when the change is a response to a bug report, you may
prefix with `Issue #123:` (where `#123` is the report ID) instead.
- If the changed code itself is not self-explanatory enough, you can add
longer change description (2 lines after the title) to explain more.
It is not mandatory, but it is never unwelcome because old code
exploration to understand why things were done (possibly years before
by people long gone) is a real thing we do all the time. So if it's
not obvious, explain us.
- Explanations can also be made in the shape of links to a bug report
(ours, or a third-party project tracker, or some manual), even though
additional text explanations may still be useful (unfortunately URLs
may change or disappear). If the link is to our own bug tracker,
usually giving the ID is enough.
- Same [as for code](#line-width), wrap your commit message to
reasonable line widths, such as 72 or 80 maximum so that other
contributors don't have to scroll horizontally on narrow
vizualisation. There may be exceptions, for instance when pasting some
error messages which may end up confusing when wrapped. But other than
this, wrap your text (most `git` client would have a feature to do it
for you).
- If the title is too long because of the max-width settings, a common
format is to break it with '…' and to continue the title 2 lines below.
Then the description goes again 2 lines below.
Here is an example of a well formatted fix in the `plug-ins/` section:
```
plug-ins: fix file-gih.
We currently cannot call gimp_pdb_run_procedure() for procedures
containing arrays because this C-type doesn't contain the size
information (which is in a second parameter but since the rule is not
hard-coded, our API can't know this).
See issue #7369.
```
Here is another as a response to a bug report and a long title:
```
Issue #6695: Wrong tab after JPG export because of "Show preview"…
… feature.
Using the new gimp_display_present() function in file-jpeg to make sure
the original display is back to the top.
```
If you want to see more good examples, this `git` command will list
commits whose messages are generally well formatted:
`git log --author="Jehan\|mitch\|Jacob Boerema"`
### Linear git log
Nearly all our repositories (`gimp-web` being the exception) have a
fully linear history. The "merge commit" workflow is definitely good and
useful in some projects' workflow, especially with bigger projects with
many contributors and subdivided maintenance roles (where the main tree
is mostly about merging public trees of several submaintainers' public
trees, who themselves applied contributed commits by individuals).
This doesn't work well with GIMP's current workflow and our number of
contributors. This is even worse with the completely useless merge
commits created by hosting tools which completely misused (or even
misunderstood) the merge concept.
This is why our Gitlab projects are configured to only push commits
linearly. This means that when a contributed tree is behind, you must
first rebase it through the "Rebase" button in the merge request (which
requires contributors to check the "*Allow commits from members who can
merge to the target branch*" option) or by rebasing in the tree then
force-pushing when Gitlab is unable to merge.
When you push directly (for contributors with push rights), you are also
expected to never push a merge commit.
### Multiple or single commits?
When contributing merge requests or patch files, you should break your
work into logical changes, not into review timelines.
E.g. after a review, instead of pushing fixes as an additional commit,
amend your commits to rewrite your local git history as though reviewed
bugs never existed.
On the other hand, we appreciate separate commits when they are logical
units. For instance, you could have 1 commit adding a GUI feature, then
1 commit adding a `libgimp` API to manipulate the new feature and 1
commit for a plug-in to use this new API. It makes perfect sense to
separate these 3 changes into their own commits and even help for review
and later dig through development logs.
## C code
### Line width
The recommended line width for source files is _80 characters_ whenever possible.
Longer lines are usually an indication that you either need a function or a
pre-processor macro.
The point is to have clear code to read and not overly long lines. Don't break
code into ugly and choppy parts to blindly follow this rule.
Function definitions in the function forward declaration block don't have to
obey the 80 characters limit. The only general rule for headers is to align the
function definitions vertically in three columns.
See more information in [Headers sections](#Headers)
### Whitespaces
#### Indentation
Each new level is indented 2 or more spaces than the previous level:
```c
if (condition)
single_statement ();
```
Use only __space characters__ to achieve this. Code indented with tabs will not
be accepted into the GIMP codebase.
Even if two spaces for each indentation level allow deeper nesting, GIMP favors
self-documenting function names that can be quite long. For this reason, you
should avoid deeply nested code.
*Note*: the only place where we use Tab indentation and alignment is the
Makefiles. In there, Tab are expected to be displayed as 8 characters
for proper display
#### Vertical spaces (new lines)
Except for one single newline at the end of the file, other empty lines (at the
beginning and the end) of a file are not allowed.
On the other hand, empty lines in the middle of code are very encouraged
for well-ventilated code. For instance gathering and separating code by
logical parts making it easy to read and understand.
#### Horizontal spaces
Always put a space before an opening parenthesis but never after:
```c
/* valid */
if (condition)
do_my_things ();
/* valid */
switch (condition)
{
}
/* invalid */
if(condition)
do_my_things();
/* invalid */
if ( condition )
do_my_things ( );
```
Do not eliminate whitespace and newlines just because something would
fit on 80 characters:
```c
/* invalid */
if (condition) foo (); else bar ();
```
#### Tab characters in strings
Use `\t` instead of literal tab inside the source code strings.
### Braces
#### If-else
Don't use curly braces for single statement blocks:
```c
/* valid */
if (condition)
single_statement ();
else
another_single_statement (arg1);
```
In the case of multiple statements, put curly braces on another indentation level:
```c
/* valid */
if (condition)
{
statement_1 ();
statement_2 ();
statement_3 ();
}
/* invalid */
if (condition) {
statement_1 ();
statement_2 ();
}
/* invalid */
if (condition)
{
statement_1 ();
statement_2 ();
}
```
The "no block for single statements" rule has only three exceptions:
_Both sides of the if-else statement_ must have curly braces when
either side of this if-else statement has braces or when
the single statement covers multiple lines, and it's followed
by else or else if (e.g., for functions with many arguments).
```c
/* valid */
if (condition)
{
a_single_statement_with_many_arguments (some_lengthy_argument,
another_lengthy_argument,
and_another_one,
plus_one);
}
else
{
another_single_statement (arg1, arg2);
}
```
② if the condition is composed of many lines:
```c
/* valid */
if (condition1 ||
(condition2 && condition3) ||
condition4 ||
(condition5 && (condition6 || condition7)))
{
a_single_statement ();
}
```
③ In the case of nested if's, the block should be placed on the outermost if:
```c
/* valid */
if (condition)
{
if (another_condition)
single_statement ();
else
another_single_statement ();
}
/* invalid */
if (condition)
if (another_condition)
single_statement ();
else if (yet_another_condition)
another_single_statement ();
```
#### Switch
A `switch()` should open a block on a new indentation level, and each case
should start on the same indentation level as the curly braces, with the
case block on a new indentation level:
```c
/* valid */
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
}
/* invalid */
switch (condition) {
case FOO: do_foo (); break;
case BAR: do_bar (); break;
}
/* invalid */
switch (condition)
{
case FOO: do_foo ();
break;
case BAR: do_bar ();
break;
}
/* invalid */
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
}
```
It is preferable, though not mandatory, to separate the various cases with
a newline:
```c
switch (condition)
{
case FOO:
do_foo ();
break;
case BAR:
do_bar ();
break;
default:
do_default ();
break;
}
```
If a case block needs to declare new variables, the same rules as the inner
blocks (see above) apply; place the break statement outside of the inner block:
```c
switch (condition)
{
case FOO:
{
int foo;
foo = do_foo ();
}
break;
...
}
```
Do not add `default:` case if your `switch ()` is supposed to handle _all cases_.
#### Random blocks
Using blocks to group code is discouraged and must not be used in newly
written code.
```c
int retval = 0;
gbool condition = retval >= 0;
statement_1 ();
statement_2 ();
/* discouraged in newly written code */
{
int var1 = 42;
gboolean res = FALSE;
res = statement_3 (var1);
retval = res ? -1 : 1;
}
```
### Conditions
Do not check boolean values for equality:
```c
/* valid */
if (another_condition)
do_bar ();
/* invalid */
if (condition == TRUE)
do_foo ();
```
Even if C handles NULL equality like a boolean, be explicit:
```c
/* valid */
if (some_pointer == NULL)
do_blah ();
/* invalid */
if (some_other_pointer)
do_blurp ();
```
When conditions split over multiple lines, the logical operators should always
go at the end of the line. Align the same level boolean operators to show
explicitly which are on the same level and which are not:
```c
/* valid */
if (condition1 &&
condition2 &&
(condition3 || (condition4 && condition5)))
{
do_blah ();
}
/* invalid */
if (condition1
|| condition2
|| condition3)
{
do_foo ();
}
```
### Variables declaration and definition
Place each variable on a new line. The variable name must be right-aligned,
taking into account pointers:
```c
/* valid */
int first = 42;
gboolean second = TRUE;
GimpObject *third = NULL;
```
Blocks of variable declaration/initialization should align the variable names,
allowing quick skimming of the variable list.
### Functions
Function header has the return type on one line; the name starting in the first
column of the following line. Prototype each parameter and place each on a
new line.
In function names, each word must be lowercase and separated by an underscore.
In the function definition, place the return value on a separate line from the
function name:
```c
void
my_function (void)
{
}
```
The parameters list must be broken into a new line for each parameter, with the
parameter names right-aligned, taking into account pointers:
```c
void
my_function (some_type_t some_param,
another_type_t *a_pointer_param,
final_type_t final_param)
{
}
```
While curly braces for function definitions should rest on a new line they
should not add an indentation level:
```c
/* valid */
static void
my_function (int parameter)
{
do_my_things ();
}
```
The alignment also holds when invoking a function:
```c
align_function_arguments (first_argument,
second_argument,
third_argument);
```
If your function name is very long, it's always better to extract arguments into
separate variables to improve readability:
```c
/* valid */
first_a = argument_the_first;
second_a = argument_the_second;
a_very_long_function_name_with_long_arguments (first_a, second_a);
```
Keep the function name and the arguments on the same line. Otherwise, it will
hurt readability.
```c
/* invalid */
a_very_long_function_name_with_long_arguments
(argument_the_first, argument_the_second);
```
### Macros
Try to avoid private macros unless strictly necessary. Remember to `#undef`
them at the end of a block or a series of functions needing them.
Use inline functions instead of private macro definitions.
Do not use public macros unless they evaluate to a constant.
### Includes
GIMP source files should never include the global `gimp.h` header, but instead
include the individual headers that are needed.
Includes must be in the following order:
0. `config.h` first;
0. System and third-party headers;
0. GIMP library headers (`libgimp*` headers);
0. GIMP core/app headers that it needs including its own;
Sort alphabetically the includes within the blocks.
```c
/* valid */
#include "config.h"
#include <gegl.h>
#include <gtk/gtk.h>
#include "libgimpbase/gimpbase.h"
#include "libgimpcolor/gimpcolor.h"
#include "core/gimp.h"
#include "core/gimpcontainer.h"
#include "gimpcolorpanel.h"
#include "gimpcontainerentry.h"
```
### Structures
When declaring a structure type use newlines to separate logical sections:
```c
/* preferred for new code*/
typedef struct
{
gint n_pages;
gint *pages;
gbool read_only;
} Pages;
```
When initializing a structure variable with constants, shortly enough
that it can be done on a single line, then you should add a space after
the opening curly brace and before the closing one, such as:
```C
GimpRGB color = { 0.0, 0.0, 0.0, GIMP_OPACITY_OPAQUE };
```
### Memory management
To dynamically allocate data on the heap, use `g_new()`. To allocate memory for
multiple small data structures, `g_slice_new()`.
When possible, all public structure types should be returned fully initialized,
either explicitly for each member or by using `g_new0()` or `g_slice_new0()`.
As a general programming rule, it is better to allocate and free data on the
same level. It is much easier to review code because you know that when you
allocate something there, then you also free it there.
```c
GeglBuffer *buffer;
void *p;
*buffer = gegl_buffer_new (some, args);
*p = g_new (something, n);
/* do stuff */
g_object_unref (buffer);
g_free (p);
```
When a transfer of ownership is unavoidable make it clear in the function
documentation.
### Comments
#### In-code explanation
The only allowed style is C-style comments `/* */`. In particular C++
comments `//` are strictly forbidden from our source.
We are not asking contributors to over-comment their code, yet we highly
value quality comments to explain complicated algorithms or non-obvious
code. Just ask yourself this: what if someone sees my code 5 years later
(another contributor or even your future self)…
- will one easily understand what you meant to do?
- In particular: if it needs to be removed later, won't one be scared to
delete now-useless code by fear of unexpected side-effects?
- Or oppositely: won't someone delete the code by mistake because it
looks useless while it was actually dealing with a very particular
(yet absolutely non-obvious) issue?
Adding links which explain well a problem or the reason for some
non-obvious code is also permitted. For instance a link to a bug report
(ours or some other projects') can sometimes be a good complement to a
comment.
Nevertheless it should not be overdone and in particular not for links
likely to disappear (personal blog posts, forums, corporate websites
which often revamp their design, breaking URLs, etc.).
#### Public API Documentation
All public APIs (i.e. any function exported in a header inside
`libgimp*/` folders) **MUST** have proper GObject-introspection (GIR) comments.
For functions, these should be placed in the source file directly above.
These annotations are also relevant for [GObject
Introspection](https://gi.readthedocs.io/en/latest/annotations/giannotations.html)
to generate bindings for other languages.
```c
/* valid */
/**
* gimp_object_set_name:
* @object: a #GimpObject
* @name: the @object's new name (transfer none)
*
* Sets the @object's name. Takes care of freeing the old name and
* emitting the ::name_changed signal if the old and new name differ.
**/
void
gimp_object_set_name (GimpObject *object,
const gchar *name)
{
...
}
```
Doc comments for macros, function types, class structs, etc., should be placed
next to the definitions, typically in headers.
#### Non-public API documentation
Project-only code (for instance any code from the `app/` folder) can be
less documented. For instance when a function has obvious naming, not
explaining it is perfectly acceptable.
Nevertheless adding documentation even for these private APIs is
welcome, especially when the usage is not as obvious as it looks, or
to make sure to advertize the proper memory handling (does it allocate
new memory? Which function to free it with? Or shouldn't the returned
memory be freed?), avoiding silly bugs and not wasting developer times
(when we have to look at the implementation to verify each time we use a
function).
In such a case, using gtk-docs syntax is still a nice idea as we will
understand it directly (even though we won't generate any docs from it).
### Public API
#### No variables
Avoid exporting variables as public API since this is cumbersome on some
platforms. It is always preferable to add getters and setters instead.
#### Def files for Windows
List all public functions alphabetically in the corresponding `.def` file.
- `app/gimpcore.def`
- `libgimp/gimp.def`
- `libgimpbase/gimpbase.def`
- etc
## Natural language text
### Base rules
Any text in GIMP source should follow these base rules:
- Our base language is US English, both for historical reason and
because this is the usual expectation with `gettext`, the
localization tool used by GIMP. In particular when variants of words
or idioms exist in several native English countries, we should choose
the US variant. Other English variants can be used in specific locales
(such as `en_GB` or `en_CA`…).
- Text meant for technical people, such as API documentation (in-code
comments, in-repository documentation, or gtk-doc/docgen style
comments for generated docs…) usually does not need localization, and
therefore can just be written in US English.
- Text meant to be viewed by all users should be translatable. In
particular in GIMP source code, it means that we need to use `gettext`
API.
- Use gender-neutral terms, in particular not using words such as "she/he"
or "her/his" is better. We should not use over-complicated wording to
achieve this and should look for simpler writing if necessary.
- Be nice and open-minded in all text, even in code comments. Remember
these will be read by others and that we are here to have fun
together, not fight.
### User-visible text in C code
As explained, C code uses the gettext API. Any text which might appear
in front of people should be translatable, with the following
exceptions:
- Error or warning output in `stderr` might often be untranslated
(because we assume these are mostly used for debugging and people who
will see these would be more comfortable with digging into issue
causes; also it makes debugging and searches in code easier).
- Technical error text in the graphical interface when it is made to be
reported to developers. Basically error messages meant for users
themselves should still be translatable. For instance, if one tries to
draw on a layer group, we'd display:
```C
_("Cannot modify the pixels of layer groups.")
```
Indeed this is an error message to give an information to the user.
It's not a bug.
Now when a crash happens, we add a translated header message to
explain a problem occured, but the core information stays in English
because we are not asking people to understand it, only report it to
us.
The most common variant of gettext API is the underscore `_()` (alias of
`gettext()`) for simple text:
```C
frame = gimp_frame_new (_("Shadows"));
```
When used in some widgets, we may want to add mnemonics for
accessibility. This is done with the underscore:
```C
label = gtk_label_new_with_mnemonic (_("_Width:"));
```
Note that it is a good idea to not change well-known mnemonics, such as
`_("_OK")`, `_("_Cancel")` or `_("_Reset")`. Also you should avoid using
the same mnemonics in 2 widgets on the same interface (even though GTK
has some way to handle mnemonic duplicate, but it's not really
practical).
Translators may (and often will) change mnemonics. It is therefore up to
them to take care of not having the same mnemonics on a same interface
in their specific locale.
When some messages cannot be translated at initialization, you must use
the no-op variant `N_()`. For instance, when we declare and initialize a
struct:
```C
static const struct
{
const gchar *name;
const gchar *description;
}
babl_descriptions[] =
{
{ "RGB u8", N_("RGB") },
[…]
{ "Y u8", N_("Grayscale") },
[…]
{ "R u8", N_("Red component") },
[…]
{ "G u8", N_("Green component") },
[…]
};
```
The normal gettext `_()` would not compile because you must initialize
struct elements with constants. `N_()` allows the gettext tools to
detect the strings which will need to go into the translator files.
Note though that these strings will still need to be translated when
used at runtime:
```C
g_hash_table_insert (babl_description_hash,
(gpointer) babl_descriptions[i].name,
gettext (babl_descriptions[i].description));
```
Finally note that for any strings which depends on a variable number,
you must use the ngettext variant:
```C
desc = g_strdup_printf (ngettext ("Crop Layer to Selection",
"Crop %d Layers to Selection",
g_list_length (layers)),
g_list_length (layers));
```
It is important to use `ngettext()` even in cases where there will
always be a count bigger than 1. Say our indexed image do not support
the monochrome (1 color) case, and even less 0 colors, then this seems
useless because we will always use the second string only:
```C
g_snprintf (buf, sizeof (buf),
ngettext ("Indexed color (monochrome)",
"Indexed color (%d colors)",
gimp_image_get_colormap_size (image)),
gimp_image_get_colormap_size (image));
```
Yet it's actually not useless as it allows translators for languages
with more plural forms to translate GIMP correctly. For instance,
[gettext documentation](https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms)
mentions the Polish language has different grammatical agreements for
2,3,4 and 5-21 or again 22-24 and so on. If we were to use solely
`_("Indexed color (%d colors)")`, Polish translators would not be able
to list all these cases (therefore GIMP would have a crappy Polish
localization), so we have to use `ngettext()` even if it feels useless
in English.
Finally when you add translated strings in a file which had none until
now, for it to be processed by `gettext`, you need to add its path in
alphabetical order in `po/POTFILES.in` for core files (or other
`POTFILES.in`, for instance `po-plug-ins/POTFILES.in` for plug-ins). We
have a test checking this, so the `make distcheck` step will fail anyway
when you forgot to add a new file with translation. Yet as developers
don't always run this step locally, the bug may be discovered during CI
builds. It is obviously prefered to not forget it hence not push code
which breaks the CI (and localization).
## Helping tools
### Git
We recommend enabling the default git pre-commit hook that detects trailing
whitespace and non-ASCII filenames for you and helps you to avoid corrupting
GIMP's tree with it.
In the terminal, navigate into your GIMP source code folder. Then do that as
follows (one command at a time):
```shell
cp -v .git/hooks/pre-commit.sample .git/hooks/pre-commit
chmod a+x .git/hooks/pre-commit
```
If any command above fails, visit your `.git/hooks/` folder and check for the
existence of `pre-commit.sample` or `pre-commit` files.
You might also find the `git-stripspace` utility helpful, which acts as a filter
to remove trailing whitespace as well as initial, final, and duplicate blank
lines.
### Code editor / Integrated Development Environment (IDE)
GIMP's codebase is not tied to a specific editor or IDE. The whole build
can be performed from anywhere, and we don't care what you write your
code with (as long as it follows syntax rules from this document).
Several configuration files were contributed across the years to
configure your favorite software to follow our coding style.
You are very welcome to use them (or improve them and contribute the
change when they are not perfect):
- [.dir-locals.el](.dir-locals.el) for Emacs;
- [.kateconfig](.kateconfig) for Kate;
- [c.vim](devel-docs/c.vim) for Vim (check the top comments to see how
to enable it automatically when opening a file in the GIMP tree).
*Note: the Kate and Emacs config file should work out-of-the-box, but
the Vim one needs to be enabled explicitly because it is too powerful,
hence is basically [unsafe](https://github.com/vim/vim/issues/1015).*
If you use another software to write code, you are welcome to contribute
coding style files following our rules.
### Code Formatter
Our project contains a `.clang-format` in the repository root.
A good way to test your code is with the following command while it's
not committed yet:
```sh
git diff -U0 --no-color | clang-format-diff -p1
```
Note that we are not considering these format rules as perfect, because
it seems the tool still cannot handle several special cases we have in
our coding style. Also we are not perfectly fond of the way it handles
long lines (when to accept lines a bit longer than the max line width or
not) as well as other rules. Therefore the current document remains the
ultimate one to verify when unsure of how to format something.
The CI for any merge request will contain a job called `clang-format`
which will also run your proposed change through the clang-format code
formatter as a soft verification of contributed patches. Note that this
job is only informational and in particular, it isn't considered a CI
failure, since — as said above — we are not perfectly happy with the
tool yet.
Nevertheless we expect new contributors to look at the result to fix
their basic coding style mistakes and free up reviewing contributors'
time.

View File

@ -135,10 +135,10 @@ 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](CODING_STYLE.md). 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!
listed in [CODING_STYLE.md](https://developer.gimp.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

View File

@ -7,12 +7,10 @@ SUBDIRS = \
performance-logs
EXTRA_DIST = \
CODING_STYLE.md \
HACKING.md \
README.md \
contexts.txt \
debug-plug-ins.txt \
exif-handling.txt \
gitlab-milestones.txt \
includes.txt \
libtool-instructions.txt \

View File

@ -383,7 +383,7 @@ Eventually we want to move this pipeline to Gitlab as well.
When writing code, any core developer is expected to follow:
- GIMP's [coding style](CODING_STYLE.md);
- GIMP's [coding style](https://developer.gimp.org/core/coding_style/);
- the [directory structure](#directory-structure-of-gimp-source-tree)
- our [header file inclusion policy](includes.txt)
@ -589,7 +589,7 @@ Developers are welcome to read the [specifications of XCF](specifications/xcf.tx
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](specifications/locks.md).
This is further explained in [the specifications of locks](https://developer.gimp.org/core/specifications/locks/).
#### UI Framework
@ -627,11 +627,11 @@ GIMP 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](exif-handling.txt) 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.
This [old document](https://developer.gimp.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

View File

@ -1,274 +0,0 @@
===================================
Compositing and layer modes in GIMP
===================================
This document describes the process of compositing layers and the layer modes
in GIMP.
License
-------
This is free documentation; you can modify and/or redistribute
it according to the terms of the GNU General Public License
as published by the Free Software Foundation, either version
2 of the license, or (at your option) any later version.
About this document
-------------------
This document was originally written by Henning Makholm and part of the
XCF file format specification. Because the topics here are more general
in the context of GIMP they have been moved into a separate document.
9. COMPOSITING AND LAYER MODES
===============================
This section describes the "flattening" process that GIMP applies
when a multi-layer image is displayed in the editor or exported to
other image file formats. It is present for reference only; an XCF
consumer may well elect to do something different with pixel data from
the layers than flattening them.
Most XCF consumers will need to react to the layer mode property of
each layer; such a reaction must be informed by knowledge of how the
different layer modes affect the flattening process. In some
applications it might be acceptable for an XCF consumer to refuse
processing images with layer modes other than "Normal", but such an
application will probably not be considered fully XCF capable by its
users.
In this section we consider primary color (or grayscale) intensities
and alpha values for pixels to be real numbers ranging from 0.0 to
1.0. This makes many of the formulas easier; the reader is asked to
keep in mind that a (linear) conversion from the integral 0..255 scale
of the actual XCF scale is implied whenever data from the XCF file is
mentioned.
Any practical implementation of the computations specified below may
suffer rounding errors; this specification do not detail how these are
to be handled. GIMP itself rounds values to an integral number of
255ths at many points in the computation. This specification does not
specify exactly which these points are, and authors of XCF renderers
that aim to reproduce the effects of GIMP's flattening down to the
least significant bits are referred to studying its source code.
In the description below, the variable letter "a" is used for alpha
values. The variable letter "r", "g", "b" are used for primary
intensities, "y" is used for grayscale intensities, and "i" is used
for color map indexed. The letter "c" is used for the complete
color information for a pixel; depending on the color mode of the
image that is either an (r,g,b) triple, a y, or a c.
The flattening process works independently for each pixel in the
canvas area. The description of some layer modes in the GIMP manual
may give the impression that they involve filters that let pixels
influence neighbor pixels, but that is not true.
This description does not attempt to preserve the color information
for completely transparent pixels in a layer. If an application uses
this color information, it should document explicitly how it behaves
when transparent pixels from several different layers cover the same
point of the canvas.
Flattening overview
-------------------
This is how to compute the flattened result for a single pixel
position (in theory, that is - efficient implementations will of
course follow this procedure or an equivalent one for many pixels in
parallel):
1. Initialize a "working pixel" (a1,c1) to be completely transparent
(that is, a1=0.0 and the value of c1 is immaterial).
2. Do the following for each visible layer in the image, starting with
the one that comes LAST in the master layer list:
3. Ignore the layer if it is the floating selection, or if it
does not overlap the pixel position in question.
4. Let (a2,c2) be the pixel data for the layer at the pixel
position in question. If the layer does not have an alpha
channel, then set a1 to 1.0.
5. If the layer is the one that the floating selection is attached
to and the floating selection overlaps the pixel position in
question, then do the following:
6. Let (a3,c3) be the pixel data for the floating selection
layer at the pixel position in question.
7. If there is a selection channel, then let x be its value
at the pixel position in question, and set a3 to a3*x.
8. Let m3 be the layer mode of the floating selection.
9. Set (a2,c2) to COMPOSITE(a2,c2, a3,c3,m3).
The COMPOSITE function is defined below.
10. If the layer has a layer mask and it is enabled, then let x be
the value of the layer mask at the pixel position in question,
and set a2 to a2*x.
11. Let m2 be the layer mode of the layer.
12. If the layer is the bottommost visible layer (i.e., if it is
the last visible layer in the master layer list) and m2 is not
"Normal" or "Dissolve", then set m2 to "Normal".
13. Set (a1,c1) to COMPOSITE(a1,c1, a2,c2,m2).
The COMPOSITE function is defined below.
14. If the flattened image is to be shown against a background of
color c0, then actually visible pixel is
COMPOSITE(1.0,c0, a1,c1,Normal).
Note that unless all layers have mode Normal, it would give the
wrong result to start by initializing (a1,c1) to (1.0,c0).
Helper functions
----------------
The following auxiliary functions are used in the definition of
COMPOSITE below:
MIN(x1,...,xn) is the least value of x1...xn
MAX(x1,...,xn) is the largest value of x1..xn
MID(x1,...,xn) = (MIN(x1,...,xn)+MAX(x1,...,xn))/2
CLAMP(x) = if x < 0 then 0.0 else if x > 1 then 1.0 else x
BLEND(a1,x1, a2,x2) = (1-k)*x1 + k*x2
where k = a2/(1-(1-a1)*(1-a2))
Layer modes
-----------
This and the following sections define the COMPOSITE function used in
the general flattening algorithm.
"Normal" mode for RGB or grayscale images is the usual mode of
compositing in computer graphics with alpha channels. In indexed
mode, the alpha value gets rounded to either 1.0 or 0.0 such that
no colors outside the color map get produced:
COMPOSITE(a1,y1, a2,y2,Normal)
= ( 1-(1-a1)*(1-a2), BLEND(a1,y1, a2,y2) )
COMPOSITE(a1,r1,g1,b1, a2,r2,g2,b2,Normal)
= ( 1-(1-a1)*(1-a2), BLEND(a1,r1, a2,r2),
BLEND(a1,g1, a2,g2),
BLEND(a1,b1, a2,b2) )
COMPOSITE(a1,i1, a2,i2,Normal) = if a2 > 0.5 then (1.0,i2) else (a1,i1)
"Dissolve" mode corresponds to randomly dithering the alpha channel to
the set {0.0, 1.0}:
COMPOSITE(a1,c1, a2,c2,Dissolve) = chose pseudo-randomly between
(1.0,c2) with probability a2
(a1,c1) with probability 1-a2
These two modes are the only ones that make sense for all of the RGB,
grayscale and indexed color models. In the indexed color model, all
layer modes except Dissolve are treated as Normal.
Most layer modes belong to the following group, which makes sense for
RGB and grayscale images, but not for indexed ones:
COMPOSITE(a1,y2, a2,y2,m)
= ( a1, BLEND(a1,y1, MIN(a1,a2),f(y1,y2, m)) )
COMPOSITE(a1,r1,g1,b1, a2,r2,g2,b2,m)
= ( a1, BLEND(a1,r2, MIN(a1,a2),f(r1,r2, m)),
BLEND(a1,g1, MIN(a1,a2),f(g1,g2, m)),
BLEND(a1,b1, MIN(a1,a2),f(b1,g2, m)) )
when 3 <= m <= 10 or 15 <= m <= 21.
The following table defines f(x1,x2,m):
Multiply: f(x1,x2, 3) = x1*x2
Screen: f(x1,x2, 4) = 1-(1-x1)*(1-x2)
Overlay: f(x1,x2, 5) = (1-x2)*x1^2 + x2*(1-(1-x2)^2)
Difference: f(x1,x2, 6) = if x1 > x2 then x1-x2 else x2-x1
Addition: f(x1,x2, 7) = CLAMP(x1+x2)
Subtract: f(x1,x2, 8) = CLAMP(x1-x2)
Darken Only: f(x1,x2, 9) = MIN(x1,x2)
Lighten Only: f(x1,x2, 10) = MAX(x1,x2)
Divide: f(x1,x2, 15) = CLAMP(x1/x2)
Dodge: f(x1,x2, 16) = CLAMP(x1/(1-x2))
Burn f(x1,x2, 17) = CLAMP(1-(1-x1)/x2)
Hard Light: f(x1,x2, 18) = if x2 < 0.5 then 2*x1*x2 else 1-2*(1-x1)(1-x2)
Soft Light: f(x1,x2, 19) = (1-x2)*x1^2 + x2*(1-(1-x2)^2)
Grain Extract: f(x1,x2, 20) = CLAMP(x1-x2+0.5)
Grain Merge: f(x1,x2, 21) = CLAMP(x1+x2-0.5)
Note that the "Overlay" and "Soft Light" modes have identical effects.
In the "Divide", "Dodge", and "Burn" modes, division by zero should
be considered to produce a number so large that CLAMP(x/0) = 1 unless
x=0, in which case CLAMP(0/0) = 0.
The remaining four layer modes only make sense in the RGB color model;
if the color mode of the image is grayscale or indexed they will be
interpreted as Normal.
COMPOSITE(a1,r1,g1,b1, a2,r2,g2,b2,m)
= ( a1, BLEND(a1,r2, MIN(a1,a2),r0),
BLEND(a1,g1, MIN(a1,a2),g0),
BLEND(a1,b1, MIN(a1,a2),b0) )
where (r0,g0,b0) = h(r1,g1,b1, r2,g2,b2, m)
when 11 <= m <= 14.
For defining these modes, we say that
(r,g,b) has the _hue_ of (r',g',b')
if r' = g' = b' and r >= g = b
or there exist p and q such that p>=0 and r=p*r'+q and b=p*b'+q and g=p*g'+q
(r,g,b) has the _value_ of (r',g',b')
if MAX(r,g,b) = MAX(r',g',b')
(r,g,b) has the _HSV-saturation_ of (r',g',b')
if r' = g' = b' = 0 and r = g = b
or MIN(r,g,b) = MAX(r,g,b)*MIN(r',g',b')/MAX(r',g',b')
(r,g,b) has the _luminosity_ of (r',g',b')
if MID(r,g,b) = MID(r',g',b')
(r,g,b) has the _HSL-saturation_ of (r',g',b')
if r' = g' = b' and r = g = b
or MAX(r,g,b)-MIN(r,g,b) = MIN(MID(r,g,b),1-MID(r,g,b)) *
(MAX(r',g',b')-MIN(r',g',b'))/MIN(MID(r',g',b'),1-MID(r',g',b'))
Mode 11: Hue (H of HSV)
h(r1,g1,b1, r2,g2,b2, 11) is
if r2=g2=b2 then (r1,g1,b1) unchanged
otherwise: the color that has
the hue of (r1,g2,b2)
the value of (r1,g1,b1)
the HSV-saturation of (r1,g1,b1)
Mode 12: Saturation (S of HSV)
h(r1,g1,b1, r2,g2,b2, 12) is the color that has
the hue of (r1,g1,b1)
the value of (r1,g1,b1)
the HSV-saturation of (r2,g2,b2)
Mode 13: Color (H and S of HSL)
h(r1,g1,b1, r2,g2,b2, 13) is the color that has
the hue of (r2,g2,b2)
the luminosity of (r1,g1,b1)
the HSL-saturation of (r2,g2,b2)
Mode 14: Value (V of HSV)
h(r1,g1,b1, r2,g2,b2, 14) is the color that has
the hue of (r1,g1,b1)
the value of (r2,g2,b2)
the HSV-saturation of (r1,g1,b1)

View File

@ -1,97 +0,0 @@
How GIMP should handle EXIF data
Bill Skaggs 1/2/05
This is a summary of how an image editing program is supposed to
handle each of the EXIF fields, according to the EXIF specs. Note
that this expresses my understanding based on a quick reading, and
should not be taken as gospel. For details on the contents of each of
these fields, consult the formal EXIF specifications, available from
http://www.exif.org/specifications.html.
(Note: according to the EXIF specs, an EXIF jpeg file must have a name
that is ASCII, in 8.3 format, with extension .JPG, but of course we
are not going to enforce this.)
Fields that should be used to set up the GIMP image when an EXIF file
is loaded, either by using them to configure the image (e.g.,
orientation), or by placing them in parasites that can be accessed by
non-exif-aware functions.
Orientation
XResolution
YResolution
ResolutionUnit
ImageDescription
Artist
Copyright
Colorspace
ComponentsConfiguration
UserComment
SubjectArea
SubjectLocation
ImageUniqueID
PixelXDimension
PixelYDimension
Fields that should be modified by GIMP when an EXIF jpeg file is
saved. A letter "M" indicates fields whose presence is mandatory
according to the spec.
Orientation
XResolution (M)
YResolution (M)
ResolutionUnit (M)
Software
DateTime
ImageDescription
Artist
Colorspace (M)
PixelXDimension (M)
PixelYDimension (M)
ComponentsConfiguration (M)
UserComment
SubsecTime
SubjectArea
SubjectLocation
FileSource
ImageUniqueID
thumbnail Compression (M)
thumbnail XResolution (M)
thumbnail YResolution (M)
thumbnail JPEGInterchangeFormat (M)
thumbnail JPEGInterchangeFormatLength (M)
Fields that should be used and saved related to color management:
TransferFunction
WhitePoint
PrimaryChromaticity
YCbCrCoefficients
ReferenceBlackWhite
Fields that should be deleted if they exist when saving a file as
jpeg, because they only apply to uncompressed (TIFF) data. This
applies both to the main image and to the thumbnail, if there is one.
ImageWidth
ImageLength
BitsPerSample
Compression
SamplesPerPixel
PhotometricInterpretation
StripOffsets
PlanarConfiguration
YCbCrSubSampling
Any field not mentioned here should be passed through unchanged.