Skip to main content

ferroui_base/media/
render_options.rs

1use crate::media::imaging::{BitmapBlendingMode, BitmapInterpolationMode};
2use crate::media::{EdgeMode, TextRenderingMode};
3use crate::Visual;
4
5/// Provides a set of options that control rendering behavior for visuals,
6/// including text rendering, bitmap interpolation, edge rendering, blending,
7/// and opacity handling.
8#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
9pub struct RenderOptions {
10    /// The text rendering mode. Superseded by the text options.
11    pub text_rendering_mode: TextRenderingMode,
12    /// The interpolation mode used when rendering bitmap images.
13    pub bitmap_interpolation_mode: BitmapInterpolationMode,
14    /// The edge rendering mode for non-text primitives.
15    pub edge_mode: EdgeMode,
16    /// The blending mode used when rendering bitmap images.
17    pub bitmap_blending_mode: BitmapBlendingMode,
18    /// Whether full opacity handling is required for the associated content.
19    pub requires_full_opacity_handling: Option<bool>,
20}
21
22impl RenderOptions {
23    /// Gets the value of the `BitmapInterpolationMode` render option for a
24    /// visual.
25    pub fn get_bitmap_interpolation_mode(visual: &Visual) -> BitmapInterpolationMode {
26        visual.render_options().bitmap_interpolation_mode
27    }
28
29    /// Sets the value of the `BitmapInterpolationMode` render option for a
30    /// visual.
31    pub fn set_bitmap_interpolation_mode(visual: &Visual, value: BitmapInterpolationMode) {
32        visual.set_render_options(RenderOptions { bitmap_interpolation_mode: value, ..visual.render_options() });
33    }
34
35    /// Gets the value of the `BitmapBlendingMode` render option for a
36    /// visual.
37    pub fn get_bitmap_blending_mode(visual: &Visual) -> BitmapBlendingMode {
38        visual.render_options().bitmap_blending_mode
39    }
40
41    /// Sets the value of the `BitmapBlendingMode` render option for a
42    /// visual.
43    pub fn set_bitmap_blending_mode(visual: &Visual, value: BitmapBlendingMode) {
44        visual.set_render_options(RenderOptions { bitmap_blending_mode: value, ..visual.render_options() });
45    }
46
47    /// Gets the value of the `EdgeMode` render option for a visual.
48    pub fn get_edge_mode(visual: &Visual) -> EdgeMode {
49        visual.render_options().edge_mode
50    }
51
52    /// Sets the value of the `EdgeMode` render option for a visual.
53    pub fn set_edge_mode(visual: &Visual, value: EdgeMode) {
54        visual.set_render_options(RenderOptions { edge_mode: value, ..visual.render_options() });
55    }
56
57    /// Gets the value of the `TextRenderingMode` render option for a visual.
58    /// Superseded by the text options.
59    pub fn get_text_rendering_mode(visual: &Visual) -> TextRenderingMode {
60        visual.render_options().text_rendering_mode
61    }
62
63    /// Sets the value of the `TextRenderingMode` render option for a visual.
64    /// Superseded by the text options.
65    pub fn set_text_rendering_mode(visual: &Visual, value: TextRenderingMode) {
66        visual.set_render_options(RenderOptions { text_rendering_mode: value, ..visual.render_options() });
67    }
68
69    /// Gets the value of the `RequiresFullOpacityHandling` render option for
70    /// a visual.
71    pub fn get_requires_full_opacity_handling(visual: &Visual) -> Option<bool> {
72        visual.render_options().requires_full_opacity_handling
73    }
74
75    /// Sets the value of the `RequiresFullOpacityHandling` render option for
76    /// a visual.
77    pub fn set_requires_full_opacity_handling(visual: &Visual, value: Option<bool>) {
78        visual.set_render_options(RenderOptions { requires_full_opacity_handling: value, ..visual.render_options() });
79    }
80
81    /// Returns options where every unspecified value of `self` is taken from
82    /// `other`.
83    pub fn merge_with(&self, other: RenderOptions) -> RenderOptions {
84        let mut bitmap_interpolation_mode = self.bitmap_interpolation_mode;
85        if bitmap_interpolation_mode == BitmapInterpolationMode::Unspecified {
86            bitmap_interpolation_mode = other.bitmap_interpolation_mode;
87        }
88
89        let mut edge_mode = self.edge_mode;
90        if edge_mode == EdgeMode::Unspecified {
91            edge_mode = other.edge_mode;
92        }
93
94        let mut text_rendering_mode = self.text_rendering_mode;
95        if text_rendering_mode == TextRenderingMode::Unspecified {
96            text_rendering_mode = other.text_rendering_mode;
97        }
98
99        let mut bitmap_blending_mode = self.bitmap_blending_mode;
100        if bitmap_blending_mode == BitmapBlendingMode::Unspecified {
101            bitmap_blending_mode = other.bitmap_blending_mode;
102        }
103
104        let requires_full_opacity_handling =
105            self.requires_full_opacity_handling.or(other.requires_full_opacity_handling);
106
107        RenderOptions {
108            bitmap_interpolation_mode,
109            edge_mode,
110            text_rendering_mode,
111            bitmap_blending_mode,
112            requires_full_opacity_handling,
113        }
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    use super::*;
120
121    #[test]
122    fn merge_with_takes_unspecified_values_from_other() {
123        let a = RenderOptions { edge_mode: EdgeMode::Aliased, ..Default::default() };
124        let b = RenderOptions {
125            edge_mode: EdgeMode::Antialias,
126            bitmap_interpolation_mode: BitmapInterpolationMode::HighQuality,
127            requires_full_opacity_handling: Some(true),
128            ..Default::default()
129        };
130        let merged = a.merge_with(b);
131        assert_eq!(EdgeMode::Aliased, merged.edge_mode);
132        assert_eq!(BitmapInterpolationMode::HighQuality, merged.bitmap_interpolation_mode);
133        assert_eq!(Some(true), merged.requires_full_opacity_handling);
134        assert_eq!(TextRenderingMode::Unspecified, merged.text_rendering_mode);
135    }
136
137    #[test]
138    fn visual_accessors_update_one_option_each() {
139        let visual = Visual::new();
140        assert_eq!(BitmapInterpolationMode::Unspecified, RenderOptions::get_bitmap_interpolation_mode(&visual));
141
142        RenderOptions::set_bitmap_interpolation_mode(&visual, BitmapInterpolationMode::LowQuality);
143        RenderOptions::set_edge_mode(&visual, EdgeMode::Aliased);
144        RenderOptions::set_bitmap_blending_mode(&visual, BitmapBlendingMode::Multiply);
145        RenderOptions::set_text_rendering_mode(&visual, TextRenderingMode::Antialias);
146        RenderOptions::set_requires_full_opacity_handling(&visual, Some(true));
147
148        assert_eq!(BitmapInterpolationMode::LowQuality, RenderOptions::get_bitmap_interpolation_mode(&visual));
149        assert_eq!(EdgeMode::Aliased, RenderOptions::get_edge_mode(&visual));
150        assert_eq!(BitmapBlendingMode::Multiply, RenderOptions::get_bitmap_blending_mode(&visual));
151        assert_eq!(TextRenderingMode::Antialias, RenderOptions::get_text_rendering_mode(&visual));
152        assert_eq!(Some(true), RenderOptions::get_requires_full_opacity_handling(&visual));
153    }
154}