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}