Skip to content
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

Update test image and add docs #107

Merged
merged 1 commit into from
Feb 1, 2024
Merged
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
1 change: 1 addition & 0 deletions mipidsi/docs/test_image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 92 additions & 34 deletions mipidsi/src/test_image.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,29 @@ use embedded_graphics_core::{
///
/// The test image can be used to check if the display is working and to
/// identify the correct orientation and color settings.
///
/// # Expected output
///
#[doc = include_str!("../docs/test_image.svg")]
///
/// Note that the gray border around the image above is only added to make the
/// white border visible on the light rustdoc theme and will not be visible when
/// the test image is drawn.
///
/// - There should be a one pixel white border around the display.
/// Modify the [display size](crate::Builder::with_display_size) and [display
/// offset](crate::Builder::with_display_offset) settings, if at least one
/// edge of the white border isn't drawn or if there is a gap between the
/// white border and the edge of the display.
/// - A white triangle should be drawn in the top left corner and the RGB label text should not be mirrored.
/// Modify the [orientation](crate::Builder::with_orientation) setting to
/// rotate and mirror the display until the test image is displayed correctly.
/// Note that the white triangle might not be visible on displays with rounded
/// corners.
/// - The colored bars should match the labels.
/// Use the [color inversion](crate::Builder::with_invert_colors) and [color
/// order](crate::Builder::with_color_order) settings until the colored bars
/// and labels match.
#[derive(Default)]
pub struct TestImage<C: RgbColor> {
color_type: PhantomData<C>,
Expand All @@ -24,8 +47,9 @@ impl<C: RgbColor> TestImage<C> {
}
}

const CORNER_SIZE: u32 = 10;
const CORNER_STROKE_WIDTH: u32 = 1;
const BORDER_WIDTH: u32 = 1;
const BORDER_PADDING: u32 = 4;
const TOP_LEFT_MARKER_SIZE: u32 = 20;

impl<C: RgbColor> Drawable for TestImage<C> {
type Color = C;
Expand All @@ -35,44 +59,78 @@ impl<C: RgbColor> Drawable for TestImage<C> {
where
D: DrawTarget<Color = Self::Color>,
{
let bounding_box = target.bounding_box();
target.fill_solid(&bounding_box, RgbColor::GREEN)?;
Character::new(G, bounding_box.center()).draw(target)?;

let rect = bounding_box.resized_width(bounding_box.size.width / 3, AnchorX::Left);
target.fill_solid(&rect, RgbColor::RED)?;
Character::new(R, rect.center()).draw(target)?;

let rect = bounding_box.resized_width(bounding_box.size.width / 3, AnchorX::Right);
target.fill_solid(&rect, RgbColor::BLUE)?;
Character::new(B, rect.center()).draw(target)?;

for anchor in [
AnchorPoint::TopLeft,
AnchorPoint::TopRight,
AnchorPoint::BottomLeft,
AnchorPoint::BottomRight,
] {
target.fill_solid(
&bounding_box.resized(Size::new(CORNER_SIZE, CORNER_STROKE_WIDTH), anchor),
C::WHITE,
)?;
target.fill_solid(
&bounding_box.resized(Size::new(CORNER_STROKE_WIDTH, CORNER_SIZE), anchor),
C::WHITE,
)?;
}
draw_border(target, BORDER_WIDTH)?;

let top_left_marker = Rectangle::new(
Point::new_equal((CORNER_STROKE_WIDTH * 3) as i32),
Size::new_equal(CORNER_SIZE - 3 * CORNER_STROKE_WIDTH),
);
target.fill_solid(&top_left_marker, C::WHITE)?;
let color_bar_area = target
.bounding_box()
.offset(-i32::try_from(BORDER_WIDTH + BORDER_PADDING).unwrap());
draw_color_bars(target, &color_bar_area)?;

draw_top_left_marker(target, &color_bar_area, TOP_LEFT_MARKER_SIZE)?;

Ok(())
}
}

/// Draws a white border around the draw target.
fn draw_border<D>(target: &mut D, width: u32) -> Result<(), D::Error>
where
D: DrawTarget,
D::Color: RgbColor,
{
let bounding_box = target.bounding_box();
let inner_box = bounding_box.offset(-i32::try_from(width).unwrap());

target.fill_contiguous(
&bounding_box,
bounding_box.points().map(|p| {
if inner_box.contains(p) {
D::Color::BLACK
} else {
D::Color::WHITE
}
}),
)
}

/// Draws RGB color bars and labels.
fn draw_color_bars<D>(target: &mut D, area: &Rectangle) -> Result<(), D::Error>
where
D: DrawTarget,
D::Color: RgbColor,
{
target.fill_solid(area, RgbColor::GREEN)?;
Character::new(G, area.center()).draw(target)?;

let rect = area.resized_width(area.size.width / 3, AnchorX::Left);
target.fill_solid(&rect, RgbColor::RED)?;
Character::new(R, rect.center()).draw(target)?;

let rect = area.resized_width(area.size.width / 3, AnchorX::Right);
target.fill_solid(&rect, RgbColor::BLUE)?;
Character::new(B, rect.center()).draw(target)?;

Ok(())
}

// Draws a triangular marker in the top left corner.
fn draw_top_left_marker<D>(target: &mut D, area: &Rectangle, size: u32) -> Result<(), D::Error>
where
D: DrawTarget,
D::Color: RgbColor,
{
let mut rect = area.resized(Size::new(size, 1), AnchorPoint::TopLeft);

while rect.size.width > 0 {
target.fill_solid(&rect, D::Color::WHITE)?;

rect.top_left.y += 1;
rect.size.width -= 1;
}

Ok(())
}

const R: &[u8] = &[
0, 0, 0, 0, 0, 0, 0, 0, 0, //
0, 0, 0, 0, 0, 0, 0, 0, 0, //
Expand Down
Loading