Skip to content

Add round pixels and orange theme #60

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ pub mod sdl2 {
pub use crate::{
display::SimulatorDisplay,
output_image::OutputImage,
output_settings::{OutputSettings, OutputSettingsBuilder},
output_settings::{OutputSettings, OutputSettingsBuilder, PixelShape},
theme::BinaryColorTheme,
window::Window,
};
29 changes: 23 additions & 6 deletions src/output_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ use embedded_graphics::{
prelude::*,
primitives::Rectangle,
};
use embedded_graphics::primitives::Circle;
use image::{
codecs::png::{CompressionType, FilterType, PngEncoder},
ImageBuffer, ImageEncoder, Luma, Rgb,
};

use crate::{display::SimulatorDisplay, output_settings::OutputSettings};
use crate::output_settings::PixelShape;

/// Output image.
///
Expand Down Expand Up @@ -74,17 +76,32 @@ where
let output_color = C::from(themed_color).to_be_bytes();
let output_color = output_color.as_ref();

for p in Rectangle::new(p * pixel_pitch, pixel_size).points() {
if let Ok((x, y)) = <(u32, u32)>::try_from(p) {
let start_index = (x + y * self.size.width) as usize * output_color.len();

self.data[start_index..start_index + output_color.len()]
.copy_from_slice(output_color)
match self.output_settings.pixel_shape {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This match should be moved outside the points loop to remove it from the hot path.

PixelShape::Square => {
for p in Rectangle::new(p * pixel_pitch, pixel_size).points() {
if let Ok((x, y)) = <(u32, u32)>::try_from(p) {
let start_index = (x + y * self.size.width) as usize * output_color.len();

self.data[start_index..start_index + output_color.len()]
.copy_from_slice(output_color)
}
}
}
PixelShape::Dot => {
for p in Circle::new(p * pixel_pitch + Point::new(pixel_pitch / 2, pixel_pitch / 2), self.output_settings.scale/ 2).points() {
if let Ok((x, y)) = <(u32, u32)>::try_from(p) {
let start_index = (x + y * self.size.width) as usize * output_color.len();

self.data[start_index..start_index + output_color.len()]
.copy_from_slice(output_color)
}
}
}
}
}
}
}
}

impl<C: OutputImageColor> OutputImage<C> {
/// Saves the image content to a PNG file.
Expand Down
23 changes: 23 additions & 0 deletions src/output_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,23 @@ pub struct OutputSettings {
pub pixel_spacing: u32,
/// Binary color theme.
pub theme: BinaryColorTheme,
/// Pixel shape.
pub pixel_shape: PixelShape,
/// Maximum frames per second shown in the window.
pub max_fps: u32,
}

/// Pixel shape.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum PixelShape {
/// Square pixels
#[default]
Square,

/// Round pixels
Dot,
}

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
Expand Down Expand Up @@ -54,6 +67,7 @@ pub struct OutputSettingsBuilder {
scale: Option<u32>,
pixel_spacing: Option<u32>,
theme: BinaryColorTheme,
pixel_shape: Option<PixelShape>,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to use an option for the pixel shape, because Square is the default:

Suggested change
pixel_shape: Option<PixelShape>,
pixel_shape: PixelShape,

max_fps: Option<u32>,
}

Expand Down Expand Up @@ -112,6 +126,14 @@ impl OutputSettingsBuilder {
self
}


/// Sets the pixel shape.
pub fn pixel_shape(mut self, pixel_shape: PixelShape) -> Self {
self.pixel_shape = Some(pixel_shape);

self
}

/// Sets the FPS limit of the window.
pub fn max_fps(mut self, max_fps: u32) -> Self {
self.max_fps = Some(max_fps);
Expand All @@ -125,6 +147,7 @@ impl OutputSettingsBuilder {
scale: self.scale.unwrap_or(1),
pixel_spacing: self.pixel_spacing.unwrap_or(0),
theme: self.theme,
pixel_shape: self.pixel_shape.unwrap_or(PixelShape::Square),
max_fps: self.max_fps.unwrap_or(60),
}
}
Expand Down
7 changes: 7 additions & 0 deletions src/theme.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ pub enum BinaryColorTheme {

/// An on/off OLED-like display with a dark blue background and light blue pixels
OledBlue,

/// An on/off OLED-like display with a black background and orange pixels
OledOrange,
}


fn map_color(color: Rgb888, color_off: Rgb888, color_on: Rgb888) -> Rgb888 {
match color {
Rgb888::BLACK => color_off,
Expand Down Expand Up @@ -54,6 +58,9 @@ impl BinaryColorTheme {
map_color(color, Rgb888::new(0, 20, 40), Rgb888::new(0, 210, 255))
}
BinaryColorTheme::OledWhite => map_color(color, Rgb888::new(20, 20, 20), Rgb888::WHITE),
BinaryColorTheme::OledOrange => {
map_color(color, Rgb888::new(0, 0, 0), Rgb888::new(255, 100, 0))
}
}
}
}