1# This file is part of MyPaint.
2# Copyright (C) 2015 by Andrew Chadwick <a.t.chadwick@gmail.com>
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8
9"""Layer mode constants"""
10
11from __future__ import division, print_function
12
13from gettext import gettext as _
14import lib.mypaintlib
15
16#: Additional pass-through mode for layer groups (not saved, but reflected
17#: into other flags which are saved)
18PASS_THROUGH_MODE = -1
19
20
21#: Valid modes for all layers
22STANDARD_MODES = tuple(range(lib.mypaintlib.NumCombineModes))
23
24
25#: Extra modes valid only for sub-stacks (groups)
26STACK_MODES = (PASS_THROUGH_MODE,)
27
28
29#: The default layer combine mode - overridable
30_DEFAULT_MODE = lib.mypaintlib.CombineSpectralWGM
31
32
33def set_default_mode(mode):
34    assert mode in STANDARD_MODES
35    global _DEFAULT_MODE
36    _DEFAULT_MODE = mode
37
38
39def default_mode():
40    return _DEFAULT_MODE
41
42
43#: UI strings (label, tooltip) for the layer modes
44MODE_STRINGS = {
45    # Group modes
46    PASS_THROUGH_MODE: (
47        _("Pass-through"),
48        _("Group contents apply directly to the group's backdrop")),
49    # Standard blend modes (using src-over compositing)
50    lib.mypaintlib.CombineNormal: (
51        _("Normal"),
52        _("The top layer only, without blending colors.")),
53    lib.mypaintlib.CombineSpectralWGM: (
54        _("Pigment"),
55        _("Similar to mixing actual pigments by upsampling "
56          "to 10 spectral channels.")),
57    lib.mypaintlib.CombineMultiply: (
58        _("Multiply"),
59        _("Similar to loading two slides into a projector and "
60          "projecting the combined result.")),
61    lib.mypaintlib.CombineScreen: (
62        _("Screen"),
63        _("Like shining two separate slide projectors onto a screen "
64          "simultaneously. This is the inverse of 'Multiply'.")),
65    lib.mypaintlib.CombineOverlay: (
66        _("Overlay"),
67        _("Overlays the backdrop with the top layer, preserving the "
68          "backdrop's highlights and shadows. This is the inverse "
69          "of 'Hard Light'.")),
70    lib.mypaintlib.CombineDarken: (
71        _("Darken"),
72        _("The top layer is used where it is darker than "
73          "the backdrop.")),
74    lib.mypaintlib.CombineLighten: (
75        _("Lighten"),
76        _("The top layer is used where it is lighter than "
77          "the backdrop.")),
78    lib.mypaintlib.CombineColorDodge: (
79        _("Dodge"),
80        _("Brightens the backdrop using the top layer. The effect is "
81          "similar to the photographic darkroom technique of the same "
82          "name which is used for improving contrast in shadows.")),
83    lib.mypaintlib.CombineColorBurn: (
84        _("Burn"),
85        _("Darkens the backdrop using the top layer. The effect looks "
86          "similar to the photographic darkroom technique of the same "
87          "name which is used for reducing over-bright highlights.")),
88    lib.mypaintlib.CombineHardLight: (
89        _("Hard Light"),
90        _("Similar to shining a harsh spotlight onto the backdrop.")),
91    lib.mypaintlib.CombineSoftLight: (
92        _("Soft Light"),
93        _("Like shining a diffuse spotlight onto the backdrop.")),
94    lib.mypaintlib.CombineDifference: (
95        _("Difference"),
96        _("Subtracts the darker color from the lighter of the two.")),
97    lib.mypaintlib.CombineExclusion: (
98        _("Exclusion"),
99        _("Similar to the 'Difference' mode, but lower in contrast.")),
100    # Nonseparable blend modes (with src-over compositing)
101    lib.mypaintlib.CombineHue: (
102        _("Hue"),
103        _("Combines the hue of the top layer with the saturation and "
104          "luminosity of the backdrop.")),
105    lib.mypaintlib.CombineSaturation: (
106        _("Saturation"),
107        _("Applies the saturation of the top layer's colors to the "
108          "hue and luminosity of the backdrop.")),
109    lib.mypaintlib.CombineColor: (
110        _("Color"),
111        _("Applies the hue and saturation of the top layer to the "
112          "luminosity of the backdrop.")),
113    lib.mypaintlib.CombineLuminosity: (
114        _("Luminosity"),
115        _("Applies the luminosity of the top layer to the hue and "
116          "saturation of the backdrop.")),
117    # Compositing operators (using normal blend mode)
118    lib.mypaintlib.CombineLighter: (
119        _("Plus"),
120        _("This layer and its backdrop are simply added together.")),
121    lib.mypaintlib.CombineDestinationIn: (
122        _("Destination In"),
123        _("Uses the backdrop only where this layer covers it. "
124          "Everything else is ignored.")),
125    lib.mypaintlib.CombineDestinationOut: (
126        _("Destination Out"),
127        _("Uses the backdrop only where this layer doesn't cover it. "
128          "Everything else is ignored.")),
129    lib.mypaintlib.CombineSourceAtop: (
130        _("Source Atop"),
131        _("Source which overlaps the destination, replaces the destination. "
132          "Destination is placed elsewhere.")),
133    lib.mypaintlib.CombineDestinationAtop: (
134        _("Destination Atop"),
135        _("Destination which overlaps the source replaces the source. "
136          "Source is placed elsewhere.")),
137}
138for mode in STANDARD_MODES + STACK_MODES:
139    assert mode in MODE_STRINGS
140
141
142#: Name to layer combine mode lookup used when loading OpenRaster
143ORA_MODES_BY_OPNAME = {
144    lib.mypaintlib.combine_mode_get_info(mode)["name"]: mode
145    for mode in range(lib.mypaintlib.NumCombineModes)
146}
147
148
149#: Layer modes which sometimes lower the alpha of their backdrop
150MODES_DECREASING_BACKDROP_ALPHA = {
151    m for m in range(lib.mypaintlib.NumCombineModes)
152    if lib.mypaintlib.combine_mode_get_info(m).get("can_decrease_alpha")
153}
154
155
156#: Layer modes which, even with alpha==0, sometimes alter their backdrops
157MODES_EFFECTIVE_AT_ZERO_ALPHA = {
158    m for m in range(lib.mypaintlib.NumCombineModes)
159    if lib.mypaintlib.combine_mode_get_info(m).get("zero_alpha_has_effect")
160}
161
162
163#: Layer modes which *always* set the backdrop's alpha to zero
164#: if their own alpha is zero.
165MODES_CLEARING_BACKDROP_AT_ZERO_ALPHA = {
166    m for m in range(lib.mypaintlib.NumCombineModes)
167    if lib.mypaintlib.combine_mode_get_info(m).get(
168        "zero_alpha_clears_backdrop"
169    )
170}
171