1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use crate::{display::SimulatorDisplay, theme::BinaryColorTheme};
use embedded_graphics::prelude::*;
/// Output settings.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct OutputSettings {
/// Pixel scale.
pub scale: u32,
/// Spacing between pixels.
pub pixel_spacing: u32,
/// Binary color theme.
pub theme: BinaryColorTheme,
}
impl OutputSettings {
/// Calculates the size of the framebuffer required to display the scaled display.
pub(crate) fn framebuffer_size<C>(&self, display: &SimulatorDisplay<C>) -> Size
where
C: PixelColor,
{
let width = display.size().width;
let height = display.size().height;
let output_width = width * self.scale + width.saturating_sub(1) * self.pixel_spacing;
let output_height = height * self.scale + height.saturating_sub(1) * self.pixel_spacing;
Size::new(output_width, output_height)
}
}
#[cfg(feature = "with-sdl")]
impl OutputSettings {
/// Translates a output coordinate to the corresponding display coordinate.
pub(crate) const fn output_to_display(&self, output_point: Point) -> Point {
let pitch = self.pixel_pitch() as i32;
Point::new(output_point.x / pitch, output_point.y / pitch)
}
pub(crate) const fn pixel_pitch(&self) -> u32 {
self.scale + self.pixel_spacing
}
}
impl Default for OutputSettings {
fn default() -> Self {
OutputSettingsBuilder::new().build()
}
}
/// Output settings builder.
pub struct OutputSettingsBuilder {
scale: Option<u32>,
pixel_spacing: Option<u32>,
theme: BinaryColorTheme,
}
impl OutputSettingsBuilder {
/// Creates new output settings builder.
pub fn new() -> Self {
Self {
scale: None,
pixel_spacing: None,
theme: BinaryColorTheme::Default,
}
}
/// Sets the pixel scale.
///
/// A scale of `2` or higher is useful for viewing the simulator on high DPI displays.
///
/// # Panics
///
/// Panics if the scale is set to `0`.
pub fn scale(mut self, scale: u32) -> Self {
assert!(scale > 0, "scale must be > 0");
self.scale = Some(scale);
self
}
/// Sets the binary color theme.
///
/// The binary color theme defines the mapping between the two display colors
/// and the output. The variants provided by the [`BinaryColorTheme`] enum
/// simulate the color scheme of commonly used display types.
///
/// Most binary color displays are relatively small individual pixels
/// are hard to recognize on higher resolution screens. Because of this
/// some scaling is automatically applied to the output when a theme is
/// set and no scaling was specified explicitly.
///
/// Note that a theme should only be set when an monochrome display is used.
/// Setting a theme when using a color display will cause an corrupted output.
///
/// [`BinaryColorTheme`]: enum.BinaryColorTheme.html
pub fn theme(mut self, theme: BinaryColorTheme) -> Self {
self.theme = theme;
self.scale.get_or_insert(3);
self.pixel_spacing.get_or_insert(1);
self
}
/// Sets the gap between pixels.
///
/// Most lower resolution displays have visible gaps between individual pixels.
/// This effect can be simulated by setting the pixel spacing to a value greater
/// than `0`.
pub fn pixel_spacing(mut self, pixel_spacing: u32) -> Self {
self.pixel_spacing = Some(pixel_spacing);
self
}
/// Builds the output settings.
pub fn build(self) -> OutputSettings {
OutputSettings {
scale: self.scale.unwrap_or(1),
pixel_spacing: self.pixel_spacing.unwrap_or(0),
theme: self.theme,
}
}
}