motion_core/drawing/blend.rs
1//! Blending, fill and mask interpretation.
2
3/// Linear-light layer blending, with explicit compositing space.
4///
5/// Separable modes evaluate straight linear channels with source-over alpha.
6/// Extended RGB is not gamut-clipped. Plus instead adds premultiplied RGB and
7/// clamps the summed alpha to one. Dodge/Burn retain their formula's intrinsic
8/// endpoints and saturation; other modes extend their piecewise formulas without
9/// input clipping. Nonseparable modes use hue/saturation/luminosity replacement.
10#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
11pub enum BlendMode {
12 /// Premultiplied source-over; the default.
13 #[default]
14 SourceOver,
15 /// Unclipped additive RGB with saturated additive alpha.
16 Plus,
17 /// Product of straight source and backdrop channels.
18 Multiply,
19 /// Source plus backdrop minus their product.
20 Screen,
21 /// Minimum of straight source and backdrop channels.
22 Darken,
23 /// Maximum of straight source and backdrop channels.
24 Lighten,
25 /// Absolute difference of straight channels.
26 Difference,
27 /// Source plus backdrop minus twice their product.
28 Exclusion,
29 /// Multiply or screen, selected by the backdrop channel at one half.
30 Overlay,
31 /// Multiply or screen, selected by the source channel at one half.
32 HardLight,
33 /// Piecewise soft lighting, with the low-backdrop cubic and upper square root.
34 SoftLight,
35 /// Backdrop divided by one minus source, saturated above at one.
36 ///
37 /// Nonpositive backdrop returns zero before source at or above one returns one.
38 ColorDodge,
39 /// One minus the saturated ratio of one minus backdrop to source.
40 ///
41 /// Backdrop at or above one returns one before nonpositive source returns zero.
42 ColorBurn,
43 /// Source hue with backdrop saturation and luminosity.
44 Hue,
45 /// Source saturation with backdrop hue and luminosity.
46 Saturation,
47 /// Source hue/saturation with backdrop luminosity.
48 Color,
49 /// Source luminosity with backdrop hue/saturation.
50 Luminosity,
51 /// Internal linear-only additive capture used by sample accumulation.
52 #[doc(hidden)]
53 LinearPlus,
54}
55
56/// Color space used for compositing, independent of stored linear pixels.
57#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
58pub enum BlendSpace {
59 /// Composite straight linear RGB, retaining the default.
60 #[default]
61 LinearRgb,
62 /// Composite encoded sRGB, then return to linear-premultiplied storage.
63 Srgb,
64}
65
66/// How closed contours determine the filled interior.
67///
68/// Recording retains both rules without silently substituting one for
69/// the default NonZero rule.
70///
71/// ```
72/// use motion_core::prelude::*;
73/// use motion_core::{
74/// DisplayList, RasterLimits, ResourcePool, ValidatedDisplayList, MAX_PATH_VERBS,
75/// MAX_STROKE_VERBS, MAX_SVG_PATH_BYTES, sample_offsets,
76/// };
77/// let path = Path2D::from_rect(Rect::new(0.0, 0.0, 10.0, 20.0))?;
78/// let fill = path.fill(Color::WHITE);
79/// let native = DrawContext::default().record(&fill, ValidationLimits::default())?;
80/// assert!(matches!(
81/// native[0],
82/// DrawCommand::Fill {
83/// rule: FillRule::NonZero,
84/// ..
85/// }
86/// ));
87/// let even = DrawContext::default().record(
88/// &fill.fill_rule(FillRule::EvenOdd),
89/// ValidationLimits::default(),
90/// )?;
91/// assert!(matches!(
92/// even[0],
93/// DrawCommand::Fill {
94/// rule: FillRule::EvenOdd,
95/// ..
96/// }
97/// ));
98/// # Ok::<(), motion_core::ValidationError>(())
99/// ```
100#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
101pub enum FillRule {
102 /// Nonzero signed winding count; the default.
103 #[default]
104 NonZero,
105 /// Odd crossing count.
106 EvenOdd,
107}
108
109/// How linear-premultiplied content becomes a layer's mask coverage.
110///
111/// Coverage is computed in the compositing color space and clamped
112/// to 0..=1 before optional inversion, without altering working colors.
113/// Alpha-zero pixels have zero ordinary coverage, even with hidden extended
114/// RGB; inverted modes therefore retain source content at those pixels.
115#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
116pub enum MaskMode {
117 /// Use only the completed mask's alpha.
118 #[default]
119 Alpha,
120 /// One minus the completed mask's alpha, including transparent artwork.
121 InvertedAlpha,
122 /// Use Rec.709 luminance of linear premultiplied RGB, already alpha-weighted.
123 Luminance,
124 /// One minus clamped linear-premultiplied luminance; alpha is not inverted first.
125 InvertedLuminance,
126}