peniko/
blend.rs

1// Copyright 2022 the Peniko Authors
2// SPDX-License-Identifier: Apache-2.0 OR MIT
3
4/// Defines the color mixing function for a [blend operation](BlendMode).
5#[derive(Copy, Clone, PartialEq, Eq, Debug)]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[repr(u8)]
8pub enum Mix {
9    /// Default attribute which specifies no blending. The blending formula simply selects the source color.
10    Normal = 0,
11    /// Source color is multiplied by the destination color and replaces the destination.
12    Multiply = 1,
13    /// Multiplies the complements of the backdrop and source color values, then complements the result.
14    Screen = 2,
15    /// Multiplies or screens the colors, depending on the backdrop color value.
16    Overlay = 3,
17    /// Selects the darker of the backdrop and source colors.
18    Darken = 4,
19    /// Selects the lighter of the backdrop and source colors.
20    Lighten = 5,
21    /// Brightens the backdrop color to reflect the source color. Painting with black produces no
22    /// change.
23    ColorDodge = 6,
24    /// Darkens the backdrop color to reflect the source color. Painting with white produces no
25    /// change.
26    ColorBurn = 7,
27    /// Multiplies or screens the colors, depending on the source color value. The effect is
28    /// similar to shining a harsh spotlight on the backdrop.
29    HardLight = 8,
30    /// Darkens or lightens the colors, depending on the source color value. The effect is similar
31    /// to shining a diffused spotlight on the backdrop.
32    SoftLight = 9,
33    /// Subtracts the darker of the two constituent colors from the lighter color.
34    Difference = 10,
35    /// Produces an effect similar to that of the `Difference` mode but lower in contrast. Painting
36    /// with white inverts the backdrop color; painting with black produces no change.
37    Exclusion = 11,
38    /// Creates a color with the hue of the source color and the saturation and luminosity of the
39    /// backdrop color.
40    Hue = 12,
41    /// Creates a color with the saturation of the source color and the hue and luminosity of the
42    /// backdrop color. Painting with this mode in an area of the backdrop that is a pure gray
43    /// (no saturation) produces no change.
44    Saturation = 13,
45    /// Creates a color with the hue and saturation of the source color and the luminosity of the
46    /// backdrop color. This preserves the gray levels of the backdrop and is useful for coloring
47    /// monochrome images or tinting color images.
48    Color = 14,
49    /// Creates a color with the luminosity of the source color and the hue and saturation of the
50    /// backdrop color. This produces an inverse effect to that of the `Color` mode.
51    Luminosity = 15,
52    /// `Clip` is the same as `Normal`, but the latter always creates an isolated blend group and the
53    /// former can optimize that out.
54    Clip = 128,
55    // NOTICE: If a new value is added, be sure to update the bytemuck CheckedBitPattern impl.
56}
57
58/// Defines the layer composition function for a [blend operation](BlendMode).
59#[derive(Copy, Clone, PartialEq, Eq, Debug)]
60#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
61#[repr(u8)]
62pub enum Compose {
63    /// No regions are enabled.
64    Clear = 0,
65    /// Only the source will be present.
66    Copy = 1,
67    /// Only the destination will be present.
68    Dest = 2,
69    /// The source is placed over the destination.
70    SrcOver = 3,
71    /// The destination is placed over the source.
72    DestOver = 4,
73    /// The parts of the source that overlap with the destination are placed.
74    SrcIn = 5,
75    /// The parts of the destination that overlap with the source are placed.
76    DestIn = 6,
77    /// The parts of the source that fall outside of the destination are placed.
78    SrcOut = 7,
79    /// The parts of the destination that fall outside of the source are placed.
80    DestOut = 8,
81    /// The parts of the source which overlap the destination replace the destination. The
82    /// destination is placed everywhere else.
83    SrcAtop = 9,
84    /// The parts of the destination which overlaps the source replace the source. The source is
85    /// placed everywhere else.
86    DestAtop = 10,
87    /// The non-overlapping regions of source and destination are combined.
88    Xor = 11,
89    /// The sum of the source image and destination image is displayed.
90    Plus = 12,
91    /// Allows two elements to cross fade by changing their opacities from 0 to 1 on one
92    /// element and 1 to 0 on the other element.
93    PlusLighter = 13,
94    // NOTICE: If a new value is added, be sure to modify `MAX_VALUE` in the bytemuck impl.
95}
96
97/// Blend mode consisting of [color mixing](Mix) and [composition functions](Compose).
98#[derive(Copy, Clone, PartialEq, Eq, Debug)]
99#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
100pub struct BlendMode {
101    /// The color mixing function.
102    pub mix: Mix,
103    /// The layer composition function.
104    pub compose: Compose,
105}
106
107impl BlendMode {
108    /// Creates a new blend mode from color mixing and layer composition
109    /// functions.
110    #[must_use]
111    pub const fn new(mix: Mix, compose: Compose) -> Self {
112        Self { mix, compose }
113    }
114}
115
116impl Default for BlendMode {
117    fn default() -> Self {
118        Self {
119            mix: Mix::Clip,
120            compose: Compose::SrcOver,
121        }
122    }
123}
124
125impl From<Mix> for BlendMode {
126    fn from(mix: Mix) -> Self {
127        Self {
128            mix,
129            compose: Compose::SrcOver,
130        }
131    }
132}
133
134impl From<Compose> for BlendMode {
135    fn from(compose: Compose) -> Self {
136        Self {
137            mix: Mix::Normal,
138            compose,
139        }
140    }
141}