1 /* GIMP - The GNU Image Manipulation Program
2  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3  *
4  * gimp-layer-modes.c
5  * Copyright (C) 2017 Michael Natterer <mitch@gimp.org>
6  *                    Øyvind Kolås <pippin@gimp.org>
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include "config.h"
23 
24 #include <glib-object.h>
25 #include <gegl.h>
26 
27 #include "../operations-types.h"
28 
29 #include "gegl/gimp-babl.h"
30 
31 #include "gimpoperationlayermode.h"
32 #include "gimpoperationlayermode-blend.h"
33 
34 #include "gimp-layer-modes.h"
35 
36 
37 typedef struct _GimpLayerModeInfo GimpLayerModeInfo;
38 
39 struct _GimpLayerModeInfo
40 {
41   GimpLayerMode             layer_mode;
42   const gchar              *op_name;
43   GimpLayerModeBlendFunc    blend_function;
44   GimpLayerModeFlags        flags;
45   GimpLayerModeContext      context;
46   GimpLayerCompositeMode    paint_composite_mode;
47   GimpLayerCompositeMode    composite_mode;
48   GimpLayerColorSpace       composite_space;
49   GimpLayerColorSpace       blend_space;
50 };
51 
52 
53 /*  static variables  */
54 
55 static const GimpLayerModeInfo layer_mode_infos[] =
56 {
57   { GIMP_LAYER_MODE_NORMAL_LEGACY,
58 
59     .op_name              = "gimp:normal",
60     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
61                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
62                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
63                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE  |
64                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
65     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
66     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
67     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
68     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
69   },
70 
71   { GIMP_LAYER_MODE_DISSOLVE,
72 
73     .op_name              = "gimp:dissolve",
74     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
75                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
76                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
77     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
78     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
79     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION
80   },
81 
82   { GIMP_LAYER_MODE_BEHIND_LEGACY,
83 
84     .op_name              = "gimp:behind",
85     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
86                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
87                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
88                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
89     .context              = GIMP_LAYER_MODE_CONTEXT_PAINT |
90                             GIMP_LAYER_MODE_CONTEXT_FILTER,
91     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
92     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
93     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
94   },
95 
96   { GIMP_LAYER_MODE_MULTIPLY_LEGACY,
97 
98     .op_name              = "gimp:multiply-legacy",
99     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
100                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
101                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
102                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
103     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
104     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
105     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
106     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
107     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
108   },
109 
110   { GIMP_LAYER_MODE_SCREEN_LEGACY,
111 
112     .op_name              = "gimp:screen-legacy",
113     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
114                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
115                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
116                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
117     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
118     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
119     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
120     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
121     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
122   },
123 
124   { GIMP_LAYER_MODE_OVERLAY_LEGACY,
125 
126     .op_name              = "gimp:softlight-legacy",
127     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
128                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
129                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
130                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
131     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
132     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
133     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
134     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
135     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
136   },
137 
138   { GIMP_LAYER_MODE_DIFFERENCE_LEGACY,
139 
140     .op_name              = "gimp:difference-legacy",
141     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
142                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
143                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
144                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
145     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
146     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
147     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
148     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
149     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
150   },
151 
152   { GIMP_LAYER_MODE_ADDITION_LEGACY,
153 
154     .op_name              = "gimp:addition-legacy",
155     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
156                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
157                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
158                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
159     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
160     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
161     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
162     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
163     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
164   },
165 
166   { GIMP_LAYER_MODE_SUBTRACT_LEGACY,
167 
168     .op_name              = "gimp:subtract-legacy",
169     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
170                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
171                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
172                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
173     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
174     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
175     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
176     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
177     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
178   },
179 
180   { GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY,
181 
182     .op_name              = "gimp:darken-only-legacy",
183     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
184                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
185                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
186                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
187     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
188     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
189     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
190     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
191     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
192   },
193 
194   { GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY,
195 
196     .op_name              = "gimp:lighten-only-legacy",
197     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
198                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
199                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
200                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
201     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
202     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
203     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
204     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
205     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
206   },
207 
208   { GIMP_LAYER_MODE_HSV_HUE_LEGACY,
209 
210     .op_name              = "gimp:hsv-hue-legacy",
211     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
212                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
213                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
214                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
215     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
216     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
217     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
218     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
219     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
220   },
221 
222   { GIMP_LAYER_MODE_HSV_SATURATION_LEGACY,
223 
224     .op_name              = "gimp:hsv-saturation-legacy",
225     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
226                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
227                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
228                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
229     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
230     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
231     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
232     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
233     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
234   },
235 
236   { GIMP_LAYER_MODE_HSL_COLOR_LEGACY,
237 
238     .op_name              = "gimp:hsl-color-legacy",
239     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
240                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
241                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
242                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
243     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
244     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
245     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
246     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
247     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
248   },
249 
250   { GIMP_LAYER_MODE_HSV_VALUE_LEGACY,
251 
252     .op_name              = "gimp:hsv-value-legacy",
253     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
254                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
255                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
256                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
257     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
258     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
259     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
260     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
261     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
262   },
263 
264   { GIMP_LAYER_MODE_DIVIDE_LEGACY,
265 
266     .op_name              = "gimp:divide-legacy",
267     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
268                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
269                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
270                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
271     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
272     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
273     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
274     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
275     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
276   },
277 
278   { GIMP_LAYER_MODE_DODGE_LEGACY,
279 
280     .op_name              = "gimp:dodge-legacy",
281     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
282                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
283                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
284                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
285     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
286     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
287     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
288     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
289     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
290   },
291 
292   { GIMP_LAYER_MODE_BURN_LEGACY,
293 
294     .op_name              = "gimp:burn-legacy",
295     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
296                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
297                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
298                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
299     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
300     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
301     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
302     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
303     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
304   },
305 
306   { GIMP_LAYER_MODE_HARDLIGHT_LEGACY,
307 
308     .op_name              = "gimp:hardlight-legacy",
309     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
310                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
311                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
312                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
313     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
314     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
315     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
316     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
317     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
318   },
319 
320   { GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
321 
322     .op_name              = "gimp:softlight-legacy",
323     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
324                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
325                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
326                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
327     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
328     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
329     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
330     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
331     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
332   },
333 
334   { GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,
335 
336     .op_name              = "gimp:grain-extract-legacy",
337     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
338                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
339                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
340                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
341     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
342     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
343     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
344     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
345     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
346   },
347 
348   { GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,
349 
350     .op_name              = "gimp:grain-merge-legacy",
351     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
352                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
353                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
354                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE,
355     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
356     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
357     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
358     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
359     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
360   },
361 
362   { GIMP_LAYER_MODE_COLOR_ERASE_LEGACY,
363 
364     .op_name              = "gimp:layer-mode",
365     .blend_function       = gimp_operation_layer_mode_blend_color_erase,
366     .flags                = GIMP_LAYER_MODE_FLAG_LEGACY                    |
367                             GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
368                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
369                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE  |
370                             GIMP_LAYER_MODE_FLAG_SUBTRACTIVE,
371     .context              = GIMP_LAYER_MODE_CONTEXT_PAINT |
372                             GIMP_LAYER_MODE_CONTEXT_FILTER,
373     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
374     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
375     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL,
376     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
377   },
378 
379   { GIMP_LAYER_MODE_OVERLAY,
380 
381     .op_name              = "gimp:layer-mode",
382     .blend_function       = gimp_operation_layer_mode_blend_overlay,
383     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
384     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
385     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
386     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
387     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
388   },
389 
390   { GIMP_LAYER_MODE_LCH_HUE,
391 
392     .op_name              = "gimp:layer-mode",
393     .blend_function       = gimp_operation_layer_mode_blend_lch_hue,
394     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
395     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
396     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
397     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
398     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
399     .blend_space          = GIMP_LAYER_COLOR_SPACE_LAB
400   },
401 
402   { GIMP_LAYER_MODE_LCH_CHROMA,
403 
404     .op_name              = "gimp:layer-mode",
405     .blend_function       = gimp_operation_layer_mode_blend_lch_chroma,
406     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
407     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
408     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
409     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
410     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
411     .blend_space          = GIMP_LAYER_COLOR_SPACE_LAB
412   },
413 
414   { GIMP_LAYER_MODE_LCH_COLOR,
415 
416     .op_name              = "gimp:layer-mode",
417     .blend_function       = gimp_operation_layer_mode_blend_lch_color,
418     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
419     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
420     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
421     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
422     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
423     .blend_space          = GIMP_LAYER_COLOR_SPACE_LAB
424   },
425 
426   { GIMP_LAYER_MODE_LCH_LIGHTNESS,
427 
428     .op_name              = "gimp:layer-mode",
429     .blend_function       = gimp_operation_layer_mode_blend_lch_lightness,
430     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
431     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
432     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
433     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
434     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
435     .blend_space          = GIMP_LAYER_COLOR_SPACE_LAB
436   },
437 
438   { GIMP_LAYER_MODE_NORMAL,
439 
440     .op_name              = "gimp:normal",
441     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE |
442                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
443     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
444     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
445     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
446     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
447   },
448 
449   { GIMP_LAYER_MODE_BEHIND,
450 
451     .op_name              = "gimp:behind",
452     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
453     .context              = GIMP_LAYER_MODE_CONTEXT_PAINT |
454                             GIMP_LAYER_MODE_CONTEXT_FILTER,
455     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
456     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
457     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
458   },
459 
460   { GIMP_LAYER_MODE_MULTIPLY,
461 
462     .op_name              = "gimp:layer-mode",
463     .blend_function       = gimp_operation_layer_mode_blend_multiply,
464     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
465     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
466     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
467     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
468     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
469   },
470 
471   { GIMP_LAYER_MODE_SCREEN,
472 
473     .op_name              = "gimp:layer-mode",
474     .blend_function       = gimp_operation_layer_mode_blend_screen,
475     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
476     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
477     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
478     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
479     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
480   },
481 
482   { GIMP_LAYER_MODE_DIFFERENCE,
483 
484     .op_name              = "gimp:layer-mode",
485     .blend_function       = gimp_operation_layer_mode_blend_difference,
486     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
487     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
488     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
489     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
490     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
491   },
492 
493   { GIMP_LAYER_MODE_ADDITION,
494 
495     .op_name              = "gimp:layer-mode",
496     .blend_function       = gimp_operation_layer_mode_blend_addition,
497     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
498     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
499     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
500     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
501     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
502   },
503 
504   { GIMP_LAYER_MODE_SUBTRACT,
505 
506     .op_name              = "gimp:layer-mode",
507     .blend_function       = gimp_operation_layer_mode_blend_subtract,
508     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
509     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
510     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
511     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
512     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
513   },
514 
515   { GIMP_LAYER_MODE_DARKEN_ONLY,
516 
517     .op_name              = "gimp:layer-mode",
518     .blend_function       = gimp_operation_layer_mode_blend_darken_only,
519     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
520     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
521     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
522     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
523     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
524     /* no blend_space: reuse composite space, no conversion thus fewer copies */
525   },
526 
527   { GIMP_LAYER_MODE_LIGHTEN_ONLY,
528 
529     .op_name              = "gimp:layer-mode",
530     .blend_function       = gimp_operation_layer_mode_blend_lighten_only,
531     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
532     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
533     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
534     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
535     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
536     /* no blend_space: reuse composite space, no conversion thus fewer copies */
537   },
538 
539   { GIMP_LAYER_MODE_HSV_HUE,
540 
541     .op_name              = "gimp:layer-mode",
542     .blend_function       = gimp_operation_layer_mode_blend_hsv_hue,
543     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
544     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
545     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
546     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
547     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
548     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
549   },
550 
551   { GIMP_LAYER_MODE_HSV_SATURATION,
552 
553     .op_name              = "gimp:layer-mode",
554     .blend_function       = gimp_operation_layer_mode_blend_hsv_saturation,
555     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
556     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
557     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
558     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
559     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
560     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
561   },
562 
563   { GIMP_LAYER_MODE_HSL_COLOR,
564 
565     .op_name              = "gimp:layer-mode",
566     .blend_function       = gimp_operation_layer_mode_blend_hsl_color,
567     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
568     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
569     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
570     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
571     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
572     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
573   },
574 
575   { GIMP_LAYER_MODE_HSV_VALUE,
576 
577     .op_name              = "gimp:layer-mode",
578     .blend_function       = gimp_operation_layer_mode_blend_hsv_value,
579     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
580     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
581     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
582     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
583     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
584     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
585   },
586 
587   { GIMP_LAYER_MODE_DIVIDE,
588 
589     .op_name              = "gimp:layer-mode",
590     .blend_function       = gimp_operation_layer_mode_blend_divide,
591     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
592     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
593     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
594     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
595     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
596   },
597 
598   { GIMP_LAYER_MODE_DODGE,
599 
600     .op_name              = "gimp:layer-mode",
601     .blend_function       = gimp_operation_layer_mode_blend_dodge,
602     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
603     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
604     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
605     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
606     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
607   },
608 
609   { GIMP_LAYER_MODE_BURN,
610 
611     .op_name              = "gimp:layer-mode",
612     .blend_function       = gimp_operation_layer_mode_blend_burn,
613     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
614     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
615     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
616     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
617     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
618   },
619 
620   { GIMP_LAYER_MODE_HARDLIGHT,
621 
622     .op_name              = "gimp:layer-mode",
623     .blend_function       = gimp_operation_layer_mode_blend_hardlight,
624     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
625     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
626     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
627     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
628     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
629   },
630 
631   { GIMP_LAYER_MODE_SOFTLIGHT,
632 
633     .op_name              = "gimp:layer-mode",
634     .blend_function       = gimp_operation_layer_mode_blend_softlight,
635     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
636     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
637     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
638     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
639     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
640   },
641 
642   { GIMP_LAYER_MODE_GRAIN_EXTRACT,
643 
644     .op_name              = "gimp:layer-mode",
645     .blend_function       = gimp_operation_layer_mode_blend_grain_extract,
646     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
647     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
648     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
649     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
650     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
651   },
652 
653   { GIMP_LAYER_MODE_GRAIN_MERGE,
654 
655     .op_name              = "gimp:layer-mode",
656     .blend_function       = gimp_operation_layer_mode_blend_grain_merge,
657     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
658     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
659     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
660     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
661     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
662   },
663 
664   { GIMP_LAYER_MODE_VIVID_LIGHT,
665 
666     .op_name              = "gimp:layer-mode",
667     .blend_function       = gimp_operation_layer_mode_blend_vivid_light,
668     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
669     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
670     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
671     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
672     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
673   },
674 
675   { GIMP_LAYER_MODE_PIN_LIGHT,
676 
677     .op_name              = "gimp:layer-mode",
678     .blend_function       = gimp_operation_layer_mode_blend_pin_light,
679     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
680     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
681     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
682     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
683     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
684   },
685 
686   { GIMP_LAYER_MODE_LINEAR_LIGHT,
687 
688     .op_name              = "gimp:layer-mode",
689     .blend_function       = gimp_operation_layer_mode_blend_linear_light,
690     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
691     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
692     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
693     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
694     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
695   },
696 
697   { GIMP_LAYER_MODE_HARD_MIX,
698 
699     .op_name              = "gimp:layer-mode",
700     .blend_function       = gimp_operation_layer_mode_blend_hard_mix,
701     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
702     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
703     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
704     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
705     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
706   },
707 
708   { GIMP_LAYER_MODE_EXCLUSION,
709 
710     .op_name              = "gimp:layer-mode",
711     .blend_function       = gimp_operation_layer_mode_blend_exclusion,
712     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
713     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
714     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
715     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
716     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
717   },
718 
719   { GIMP_LAYER_MODE_LINEAR_BURN,
720 
721     .op_name              = "gimp:layer-mode",
722     .blend_function       = gimp_operation_layer_mode_blend_linear_burn,
723     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
724     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
725     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
726     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
727     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
728   },
729 
730   { GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,
731 
732     .op_name              = "gimp:layer-mode",
733     .blend_function       = gimp_operation_layer_mode_blend_luma_darken_only,
734     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
735     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
736     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
737     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
738     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
739   },
740 
741   { GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,
742 
743     .op_name              = "gimp:layer-mode",
744     .blend_function       = gimp_operation_layer_mode_blend_luma_lighten_only,
745     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
746     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
747     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
748     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
749     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL
750   },
751 
752   { GIMP_LAYER_MODE_LUMINANCE,
753 
754     .op_name              = "gimp:layer-mode",
755     .blend_function       = gimp_operation_layer_mode_blend_luminance,
756     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE,
757     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
758     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
759     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
760     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
761     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
762   },
763 
764   { GIMP_LAYER_MODE_COLOR_ERASE,
765 
766     .op_name              = "gimp:layer-mode",
767     .blend_function       = gimp_operation_layer_mode_blend_color_erase,
768     .flags                = GIMP_LAYER_MODE_FLAG_SUBTRACTIVE,
769     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
770     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
771     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
772     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR,
773     .blend_space          = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
774   },
775 
776   { GIMP_LAYER_MODE_ERASE,
777 
778     .op_name              = "gimp:erase",
779     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE |
780                             GIMP_LAYER_MODE_FLAG_SUBTRACTIVE           |
781                             GIMP_LAYER_MODE_FLAG_ALPHA_ONLY            |
782                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
783     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
784     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
785     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
786     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
787   },
788 
789   { GIMP_LAYER_MODE_MERGE,
790 
791     .op_name              = "gimp:merge",
792     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE |
793                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
794     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
795     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
796     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
797     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
798   },
799 
800   { GIMP_LAYER_MODE_SPLIT,
801 
802     .op_name              = "gimp:split",
803     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
804                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
805                             GIMP_LAYER_MODE_FLAG_SUBTRACTIVE               |
806                             GIMP_LAYER_MODE_FLAG_ALPHA_ONLY                |
807                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
808     .context              = GIMP_LAYER_MODE_CONTEXT_ALL,
809     .paint_composite_mode = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP,
810     .composite_mode       = GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP
811   },
812 
813   { GIMP_LAYER_MODE_PASS_THROUGH,
814 
815     .op_name              = "gimp:pass-through",
816     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE    |
817                             GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE |
818                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
819     .context              = GIMP_LAYER_MODE_CONTEXT_GROUP,
820     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
821     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
822   },
823 
824   { GIMP_LAYER_MODE_REPLACE,
825 
826     .op_name              = "gimp:replace",
827     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE |
828                             GIMP_LAYER_MODE_FLAG_TRIVIAL,
829     .context              = GIMP_LAYER_MODE_CONTEXT_FILTER,
830     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
831     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION,
832     .composite_space      = GIMP_LAYER_COLOR_SPACE_RGB_LINEAR
833   },
834 
835   { GIMP_LAYER_MODE_ANTI_ERASE,
836 
837     .op_name              = "gimp:anti-erase",
838     .flags                = GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE     |
839                             GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE |
840                             GIMP_LAYER_MODE_FLAG_ALPHA_ONLY,
841     .paint_composite_mode = GIMP_LAYER_COMPOSITE_UNION,
842     .composite_mode       = GIMP_LAYER_COMPOSITE_UNION
843   }
844 };
845 
846 static const GimpLayerMode layer_mode_group_default[] =
847 {
848   GIMP_LAYER_MODE_PASS_THROUGH,
849 
850   GIMP_LAYER_MODE_SEPARATOR,
851 
852   GIMP_LAYER_MODE_REPLACE,
853 
854   GIMP_LAYER_MODE_SEPARATOR,
855 
856   GIMP_LAYER_MODE_NORMAL,
857   GIMP_LAYER_MODE_DISSOLVE,
858   GIMP_LAYER_MODE_BEHIND,
859   GIMP_LAYER_MODE_COLOR_ERASE,
860   GIMP_LAYER_MODE_ERASE,
861   GIMP_LAYER_MODE_ANTI_ERASE,
862   GIMP_LAYER_MODE_MERGE,
863   GIMP_LAYER_MODE_SPLIT,
864 
865   GIMP_LAYER_MODE_SEPARATOR,
866 
867   GIMP_LAYER_MODE_LIGHTEN_ONLY,
868   GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,
869   GIMP_LAYER_MODE_SCREEN,
870   GIMP_LAYER_MODE_DODGE,
871   GIMP_LAYER_MODE_ADDITION,
872 
873   GIMP_LAYER_MODE_SEPARATOR,
874 
875   GIMP_LAYER_MODE_DARKEN_ONLY,
876   GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,
877   GIMP_LAYER_MODE_MULTIPLY,
878   GIMP_LAYER_MODE_BURN,
879   GIMP_LAYER_MODE_LINEAR_BURN,
880 
881   GIMP_LAYER_MODE_SEPARATOR,
882 
883   GIMP_LAYER_MODE_OVERLAY,
884   GIMP_LAYER_MODE_SOFTLIGHT,
885   GIMP_LAYER_MODE_HARDLIGHT,
886   GIMP_LAYER_MODE_VIVID_LIGHT,
887   GIMP_LAYER_MODE_PIN_LIGHT,
888   GIMP_LAYER_MODE_LINEAR_LIGHT,
889   GIMP_LAYER_MODE_HARD_MIX,
890 
891   GIMP_LAYER_MODE_SEPARATOR,
892 
893   GIMP_LAYER_MODE_DIFFERENCE,
894   GIMP_LAYER_MODE_EXCLUSION,
895   GIMP_LAYER_MODE_SUBTRACT,
896   GIMP_LAYER_MODE_GRAIN_EXTRACT,
897   GIMP_LAYER_MODE_GRAIN_MERGE,
898   GIMP_LAYER_MODE_DIVIDE,
899 
900   GIMP_LAYER_MODE_SEPARATOR,
901 
902   GIMP_LAYER_MODE_HSV_HUE,
903   GIMP_LAYER_MODE_HSV_SATURATION,
904   GIMP_LAYER_MODE_HSL_COLOR,
905   GIMP_LAYER_MODE_HSV_VALUE,
906 
907   GIMP_LAYER_MODE_SEPARATOR,
908 
909   GIMP_LAYER_MODE_LCH_HUE,
910   GIMP_LAYER_MODE_LCH_CHROMA,
911   GIMP_LAYER_MODE_LCH_COLOR,
912   GIMP_LAYER_MODE_LCH_LIGHTNESS,
913   GIMP_LAYER_MODE_LUMINANCE
914 };
915 
916 static const GimpLayerMode layer_mode_group_legacy[] =
917 {
918   GIMP_LAYER_MODE_NORMAL_LEGACY,
919   GIMP_LAYER_MODE_DISSOLVE,
920   GIMP_LAYER_MODE_BEHIND_LEGACY,
921   GIMP_LAYER_MODE_COLOR_ERASE_LEGACY,
922 
923   GIMP_LAYER_MODE_SEPARATOR,
924 
925   GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY,
926   GIMP_LAYER_MODE_SCREEN_LEGACY,
927   GIMP_LAYER_MODE_DODGE_LEGACY,
928   GIMP_LAYER_MODE_ADDITION_LEGACY,
929 
930   GIMP_LAYER_MODE_SEPARATOR,
931 
932   GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY,
933   GIMP_LAYER_MODE_MULTIPLY_LEGACY,
934   GIMP_LAYER_MODE_BURN_LEGACY,
935 
936   GIMP_LAYER_MODE_SEPARATOR,
937 
938   GIMP_LAYER_MODE_OVERLAY,
939   GIMP_LAYER_MODE_SOFTLIGHT_LEGACY,
940   GIMP_LAYER_MODE_HARDLIGHT_LEGACY,
941 
942   GIMP_LAYER_MODE_SEPARATOR,
943 
944   GIMP_LAYER_MODE_DIFFERENCE_LEGACY,
945   GIMP_LAYER_MODE_SUBTRACT_LEGACY,
946   GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY,
947   GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY,
948   GIMP_LAYER_MODE_DIVIDE_LEGACY,
949 
950   GIMP_LAYER_MODE_SEPARATOR,
951 
952   GIMP_LAYER_MODE_HSV_HUE_LEGACY,
953   GIMP_LAYER_MODE_HSV_SATURATION_LEGACY,
954   GIMP_LAYER_MODE_HSL_COLOR_LEGACY,
955   GIMP_LAYER_MODE_HSV_VALUE_LEGACY
956 };
957 
958 static const GimpLayerMode layer_mode_groups[][2] =
959 {
960   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_NORMAL,
961     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_NORMAL_LEGACY
962   },
963 
964   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_DISSOLVE,
965     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_DISSOLVE
966   },
967 
968   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_BEHIND,
969     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_BEHIND_LEGACY
970   },
971 
972   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_MULTIPLY,
973     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_MULTIPLY_LEGACY
974   },
975 
976   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_SCREEN,
977     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_SCREEN_LEGACY
978   },
979 
980   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_OVERLAY,
981     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
982   },
983 
984   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_DIFFERENCE,
985     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_DIFFERENCE_LEGACY
986   },
987 
988   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_ADDITION,
989     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_ADDITION_LEGACY
990   },
991 
992   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_SUBTRACT,
993     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_SUBTRACT_LEGACY
994   },
995 
996   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_DARKEN_ONLY,
997     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_DARKEN_ONLY_LEGACY
998   },
999 
1000   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LIGHTEN_ONLY,
1001     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_LIGHTEN_ONLY_LEGACY
1002   },
1003 
1004   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HSV_HUE,
1005     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_HSV_HUE_LEGACY
1006   },
1007 
1008   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HSV_SATURATION,
1009     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_HSV_SATURATION_LEGACY
1010   },
1011 
1012   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HSL_COLOR,
1013     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_HSL_COLOR_LEGACY
1014   },
1015 
1016   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HSV_VALUE,
1017     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_HSV_VALUE_LEGACY
1018   },
1019 
1020   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_DIVIDE,
1021     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_DIVIDE_LEGACY
1022   },
1023 
1024   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_DODGE,
1025     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_DODGE_LEGACY
1026   },
1027 
1028   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_BURN,
1029     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_BURN_LEGACY
1030   },
1031 
1032   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HARDLIGHT,
1033     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_HARDLIGHT_LEGACY
1034   },
1035 
1036   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_SOFTLIGHT,
1037     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_SOFTLIGHT_LEGACY
1038   },
1039 
1040   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_GRAIN_EXTRACT,
1041     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_GRAIN_EXTRACT_LEGACY
1042   },
1043 
1044   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_GRAIN_MERGE,
1045     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_GRAIN_MERGE_LEGACY
1046   },
1047 
1048   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_COLOR_ERASE,
1049     [GIMP_LAYER_MODE_GROUP_LEGACY ] = GIMP_LAYER_MODE_COLOR_ERASE_LEGACY,
1050   },
1051 
1052   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_VIVID_LIGHT,
1053     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1054   },
1055 
1056   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_PIN_LIGHT,
1057     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1058   },
1059 
1060   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LINEAR_LIGHT,
1061     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1062   },
1063 
1064   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_HARD_MIX,
1065     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1066   },
1067 
1068   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_EXCLUSION,
1069     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1070   },
1071 
1072   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LINEAR_BURN,
1073     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1074   },
1075 
1076   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LUMA_DARKEN_ONLY,
1077     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1078   },
1079 
1080   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LUMA_LIGHTEN_ONLY,
1081     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1082   },
1083 
1084   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_LUMINANCE,
1085     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1086   },
1087 
1088   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_ERASE,
1089     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1090   },
1091 
1092   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_MERGE,
1093     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1094   },
1095 
1096   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_SPLIT,
1097     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1098   },
1099 
1100   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_PASS_THROUGH,
1101     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1,
1102   },
1103 
1104   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_REPLACE,
1105     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1106   },
1107 
1108   { [GIMP_LAYER_MODE_GROUP_DEFAULT] = GIMP_LAYER_MODE_ANTI_ERASE,
1109     [GIMP_LAYER_MODE_GROUP_LEGACY ] = -1
1110   }
1111 };
1112 
1113 
1114 /*  public functions  */
1115 
1116 void
gimp_layer_modes_init(void)1117 gimp_layer_modes_init (void)
1118 {
1119   gint i;
1120 
1121   for (i = 0; i < G_N_ELEMENTS (layer_mode_infos); i++)
1122     {
1123       gimp_assert ((GimpLayerMode) i == layer_mode_infos[i].layer_mode);
1124     }
1125 }
1126 
1127 static const GimpLayerModeInfo *
gimp_layer_mode_info(GimpLayerMode mode)1128 gimp_layer_mode_info (GimpLayerMode mode)
1129 {
1130   g_return_val_if_fail (mode >= 0 && mode < G_N_ELEMENTS (layer_mode_infos),
1131                         &layer_mode_infos[0]);
1132 
1133   return &layer_mode_infos[mode];
1134 }
1135 
1136 gboolean
gimp_layer_mode_is_legacy(GimpLayerMode mode)1137 gimp_layer_mode_is_legacy (GimpLayerMode mode)
1138 {
1139   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1140 
1141   if (! info)
1142     return FALSE;
1143 
1144   return (info->flags & GIMP_LAYER_MODE_FLAG_LEGACY) != 0;
1145 }
1146 
1147 gboolean
gimp_layer_mode_is_blend_space_mutable(GimpLayerMode mode)1148 gimp_layer_mode_is_blend_space_mutable (GimpLayerMode mode)
1149 {
1150   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1151 
1152   if (! info)
1153     return FALSE;
1154 
1155   return (info->flags & GIMP_LAYER_MODE_FLAG_BLEND_SPACE_IMMUTABLE) == 0;
1156 }
1157 
1158 gboolean
gimp_layer_mode_is_composite_space_mutable(GimpLayerMode mode)1159 gimp_layer_mode_is_composite_space_mutable (GimpLayerMode mode)
1160 {
1161   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1162 
1163   if (! info)
1164     return FALSE;
1165 
1166   return (info->flags & GIMP_LAYER_MODE_FLAG_COMPOSITE_SPACE_IMMUTABLE) == 0;
1167 }
1168 
1169 gboolean
gimp_layer_mode_is_composite_mode_mutable(GimpLayerMode mode)1170 gimp_layer_mode_is_composite_mode_mutable (GimpLayerMode mode)
1171 {
1172   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1173 
1174   if (! info)
1175     return FALSE;
1176 
1177   return (info->flags & GIMP_LAYER_MODE_FLAG_COMPOSITE_MODE_IMMUTABLE) == 0;
1178 }
1179 
1180 gboolean
gimp_layer_mode_is_subtractive(GimpLayerMode mode)1181 gimp_layer_mode_is_subtractive (GimpLayerMode mode)
1182 {
1183   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1184 
1185   if (! info)
1186     return FALSE;
1187 
1188   return (info->flags & GIMP_LAYER_MODE_FLAG_SUBTRACTIVE) != 0;
1189 }
1190 
1191 gboolean
gimp_layer_mode_is_alpha_only(GimpLayerMode mode)1192 gimp_layer_mode_is_alpha_only (GimpLayerMode mode)
1193 {
1194   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1195 
1196   if (! info)
1197     return FALSE;
1198 
1199   return (info->flags & GIMP_LAYER_MODE_FLAG_ALPHA_ONLY) != 0;
1200 }
1201 
1202 gboolean
gimp_layer_mode_is_trivial(GimpLayerMode mode)1203 gimp_layer_mode_is_trivial (GimpLayerMode mode)
1204 {
1205   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1206 
1207   if (! info)
1208     return FALSE;
1209 
1210   return (info->flags & GIMP_LAYER_MODE_FLAG_TRIVIAL) != 0;
1211 }
1212 
1213 GimpLayerColorSpace
gimp_layer_mode_get_blend_space(GimpLayerMode mode)1214 gimp_layer_mode_get_blend_space (GimpLayerMode mode)
1215 {
1216   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1217 
1218   if (! info)
1219     return GIMP_LAYER_COLOR_SPACE_RGB_LINEAR;
1220 
1221   return info->blend_space;
1222 }
1223 
1224 GimpLayerColorSpace
gimp_layer_mode_get_composite_space(GimpLayerMode mode)1225 gimp_layer_mode_get_composite_space (GimpLayerMode mode)
1226 {
1227   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1228 
1229   if (! info)
1230     return GIMP_LAYER_COLOR_SPACE_RGB_LINEAR;
1231 
1232   return info->composite_space;
1233 }
1234 
1235 GimpLayerCompositeMode
gimp_layer_mode_get_composite_mode(GimpLayerMode mode)1236 gimp_layer_mode_get_composite_mode (GimpLayerMode mode)
1237 {
1238   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1239 
1240   if (! info)
1241     return GIMP_LAYER_COMPOSITE_UNION;
1242 
1243   return info->composite_mode;
1244 }
1245 
1246 GimpLayerCompositeMode
gimp_layer_mode_get_paint_composite_mode(GimpLayerMode mode)1247 gimp_layer_mode_get_paint_composite_mode (GimpLayerMode mode)
1248 {
1249   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1250 
1251   if (! info)
1252     return GIMP_LAYER_COMPOSITE_UNION;
1253 
1254   return info->paint_composite_mode;
1255 }
1256 
1257 const gchar *
gimp_layer_mode_get_operation(GimpLayerMode mode)1258 gimp_layer_mode_get_operation (GimpLayerMode mode)
1259 {
1260   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1261 
1262   if (! info)
1263     return "gimp:layer-mode";
1264 
1265   return info->op_name;
1266 }
1267 
1268 GimpLayerModeFunc
gimp_layer_mode_get_function(GimpLayerMode mode)1269 gimp_layer_mode_get_function (GimpLayerMode mode)
1270 {
1271   const GimpLayerModeInfo  *info = gimp_layer_mode_info (mode);
1272   static GimpLayerModeFunc  funcs[G_N_ELEMENTS (layer_mode_infos)];
1273 
1274   if (! info)
1275     info = layer_mode_infos;
1276 
1277   mode = info - layer_mode_infos;
1278 
1279   if (! funcs[mode])
1280     {
1281       GeglNode      *node;
1282       GeglOperation *operation;
1283 
1284       node = gegl_node_new_child (NULL,
1285                                   "operation", info->op_name,
1286                                   NULL);
1287 
1288       operation = gegl_node_get_gegl_operation (node);
1289 
1290       funcs[mode] = GIMP_OPERATION_LAYER_MODE_GET_CLASS (operation)->process;
1291 
1292       g_object_unref (node);
1293     }
1294 
1295   return funcs[mode];
1296 }
1297 
1298 GimpLayerModeBlendFunc
gimp_layer_mode_get_blend_function(GimpLayerMode mode)1299 gimp_layer_mode_get_blend_function (GimpLayerMode mode)
1300 {
1301   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1302 
1303   if (! info)
1304     return NULL;
1305 
1306   return info->blend_function;
1307 }
1308 
1309 GimpLayerModeContext
gimp_layer_mode_get_context(GimpLayerMode mode)1310 gimp_layer_mode_get_context (GimpLayerMode mode)
1311 {
1312   const GimpLayerModeInfo *info = gimp_layer_mode_info (mode);
1313 
1314   if (! info)
1315     return 0;
1316 
1317   return info->context;
1318 }
1319 
1320 GimpLayerMode *
gimp_layer_mode_get_context_array(GimpLayerMode mode,GimpLayerModeContext context,gint * n_modes)1321 gimp_layer_mode_get_context_array (GimpLayerMode         mode,
1322                                    GimpLayerModeContext  context,
1323                                    gint                 *n_modes)
1324 {
1325   GimpLayerModeGroup   group;
1326   const GimpLayerMode *group_modes;
1327   gint                 n_group_modes;
1328   GimpLayerMode       *array;
1329   gint                 i;
1330 
1331   group = gimp_layer_mode_get_group (mode);
1332 
1333   group_modes = gimp_layer_mode_get_group_array (group, &n_group_modes);
1334 
1335   array = g_new0 (GimpLayerMode, n_group_modes);
1336   *n_modes = 0;
1337 
1338   for (i = 0; i < n_group_modes; i++)
1339     {
1340       if (group_modes[i] != GIMP_LAYER_MODE_SEPARATOR &&
1341           (gimp_layer_mode_get_context (group_modes[i]) & context))
1342         {
1343           array[*n_modes] = group_modes[i];
1344           (*n_modes)++;
1345         }
1346     }
1347 
1348   return array;
1349 }
1350 
1351 static gboolean
is_mode_in_array(const GimpLayerMode * modes,gint n_modes,GimpLayerMode mode)1352 is_mode_in_array (const GimpLayerMode *modes,
1353                   gint                 n_modes,
1354                   GimpLayerMode        mode)
1355 {
1356   gint i;
1357 
1358   for (i = 0; i < n_modes; i++)
1359     {
1360       if (modes[i] == mode)
1361         return TRUE;
1362     }
1363 
1364   return FALSE;
1365 }
1366 
1367 GimpLayerModeGroup
gimp_layer_mode_get_group(GimpLayerMode mode)1368 gimp_layer_mode_get_group (GimpLayerMode mode)
1369 {
1370   if (is_mode_in_array (layer_mode_group_default,
1371                         G_N_ELEMENTS (layer_mode_group_default), mode))
1372     {
1373       return GIMP_LAYER_MODE_GROUP_DEFAULT;
1374     }
1375   else if (is_mode_in_array (layer_mode_group_legacy,
1376                              G_N_ELEMENTS (layer_mode_group_legacy), mode))
1377     {
1378       return GIMP_LAYER_MODE_GROUP_LEGACY;
1379     }
1380 
1381   return GIMP_LAYER_MODE_GROUP_DEFAULT;
1382 }
1383 
1384 const GimpLayerMode *
gimp_layer_mode_get_group_array(GimpLayerModeGroup group,gint * n_modes)1385 gimp_layer_mode_get_group_array (GimpLayerModeGroup  group,
1386                                  gint               *n_modes)
1387 {
1388   g_return_val_if_fail (n_modes != NULL, NULL);
1389 
1390   switch (group)
1391     {
1392     case GIMP_LAYER_MODE_GROUP_DEFAULT:
1393       *n_modes = G_N_ELEMENTS (layer_mode_group_default);
1394       return layer_mode_group_default;
1395 
1396     case GIMP_LAYER_MODE_GROUP_LEGACY:
1397       *n_modes = G_N_ELEMENTS (layer_mode_group_legacy);
1398       return layer_mode_group_legacy;
1399 
1400     default:
1401       g_return_val_if_reached (NULL);
1402     }
1403 }
1404 
1405 gboolean
gimp_layer_mode_get_for_group(GimpLayerMode old_mode,GimpLayerModeGroup new_group,GimpLayerMode * new_mode)1406 gimp_layer_mode_get_for_group (GimpLayerMode       old_mode,
1407                                GimpLayerModeGroup  new_group,
1408                                GimpLayerMode      *new_mode)
1409 {
1410   gint i;
1411 
1412   g_return_val_if_fail (new_mode != NULL, FALSE);
1413 
1414   for (i = 0; i < G_N_ELEMENTS (layer_mode_groups); i++)
1415     {
1416       if (is_mode_in_array (layer_mode_groups[i], 2, old_mode))
1417         {
1418           *new_mode = layer_mode_groups[i][new_group];
1419 
1420           if (*new_mode != -1)
1421             return TRUE;
1422 
1423           return FALSE;
1424         }
1425     }
1426 
1427   *new_mode = -1;
1428 
1429   return FALSE;
1430 }
1431 
1432 const Babl *
gimp_layer_mode_get_format(GimpLayerMode mode,GimpLayerColorSpace blend_space,GimpLayerColorSpace composite_space,GimpLayerCompositeMode composite_mode,const Babl * preferred_format)1433 gimp_layer_mode_get_format (GimpLayerMode           mode,
1434                             GimpLayerColorSpace     blend_space,
1435                             GimpLayerColorSpace     composite_space,
1436                             GimpLayerCompositeMode  composite_mode,
1437                             const Babl             *preferred_format)
1438 {
1439   GimpLayerCompositeRegion composite_region;
1440 
1441   /* for now, all modes perform i/o in the composite space. */
1442   (void) mode;
1443   (void) blend_space;
1444 
1445   if (composite_space == GIMP_LAYER_COLOR_SPACE_AUTO)
1446     composite_space = gimp_layer_mode_get_composite_space (mode);
1447 
1448   if (composite_mode == GIMP_LAYER_COMPOSITE_AUTO)
1449     composite_mode = gimp_layer_mode_get_composite_mode (mode);
1450 
1451   composite_region = gimp_layer_mode_get_included_region (mode, composite_mode);
1452 
1453   if (gimp_layer_mode_is_alpha_only (mode))
1454     {
1455       if (composite_region != GIMP_LAYER_COMPOSITE_REGION_UNION)
1456         {
1457           /* alpha-only layer modes don't combine colors in non-union composite
1458            * modes, hence we can disregard the composite space.
1459            */
1460           composite_space = GIMP_LAYER_COLOR_SPACE_AUTO;
1461         }
1462     }
1463   else if (gimp_layer_mode_is_trivial (mode))
1464     {
1465       if (! (composite_region & GIMP_LAYER_COMPOSITE_REGION_DESTINATION))
1466         {
1467           /* trivial layer modes don't combine colors when only the source
1468            * region is included, hence we can disregard the composite space.
1469            */
1470           composite_space = GIMP_LAYER_COLOR_SPACE_AUTO;
1471         }
1472     }
1473 
1474   switch (composite_space)
1475     {
1476     case GIMP_LAYER_COLOR_SPACE_AUTO:
1477       /* compositing is color-space agnostic.  return a format that has a fast
1478        * conversion path to/from the preferred format.
1479        */
1480       if (! preferred_format || gimp_babl_format_get_linear (preferred_format))
1481         return babl_format ("RGBA float");
1482       else
1483         return babl_format ("R'G'B'A float");
1484 
1485     case GIMP_LAYER_COLOR_SPACE_RGB_LINEAR:
1486       return babl_format ("RGBA float");
1487 
1488     case GIMP_LAYER_COLOR_SPACE_RGB_PERCEPTUAL:
1489       return babl_format ("R'G'B'A float");
1490 
1491     case GIMP_LAYER_COLOR_SPACE_LAB:
1492       return babl_format ("CIE Lab alpha float");
1493     }
1494 
1495   g_return_val_if_reached (babl_format ("RGBA float"));
1496 }
1497 
1498 GimpLayerCompositeRegion
gimp_layer_mode_get_included_region(GimpLayerMode mode,GimpLayerCompositeMode composite_mode)1499 gimp_layer_mode_get_included_region (GimpLayerMode          mode,
1500                                      GimpLayerCompositeMode composite_mode)
1501 {
1502   if (composite_mode == GIMP_LAYER_COMPOSITE_AUTO)
1503     composite_mode = gimp_layer_mode_get_composite_mode (mode);
1504 
1505   switch (composite_mode)
1506     {
1507     case GIMP_LAYER_COMPOSITE_UNION:
1508       return GIMP_LAYER_COMPOSITE_REGION_UNION;
1509 
1510     case GIMP_LAYER_COMPOSITE_CLIP_TO_BACKDROP:
1511       return GIMP_LAYER_COMPOSITE_REGION_DESTINATION;
1512 
1513     case GIMP_LAYER_COMPOSITE_CLIP_TO_LAYER:
1514       return GIMP_LAYER_COMPOSITE_REGION_SOURCE;
1515 
1516     case GIMP_LAYER_COMPOSITE_INTERSECTION:
1517       return GIMP_LAYER_COMPOSITE_REGION_INTERSECTION;
1518 
1519     default:
1520       g_return_val_if_reached (GIMP_LAYER_COMPOSITE_REGION_INTERSECTION);
1521     }
1522 }
1523