Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
9 changes: 9 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]
resolver = "3"
members = ["mousefood", "examples/*"]
members = ["mousefood", "mousefood-extras", "examples/*"]
default-members = ["mousefood"]

[workspace.package]
Expand Down
20 changes: 20 additions & 0 deletions mousefood-extras/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[package]
name = "mousefood-extras"
# TODO:
# description = "???"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I changed this to

description = "Widgets for mousefood logo"

version = "0.1.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
homepage.workspace = true
repository.workspace = true

# TODO: these fields??
# keywords = ["embedded-graphics", "ratatui", "tui"]
# categories = ["embedded"]
# exclude = ["/.github", "/assets"]
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This relates to embedded-graphics only by-proxy. I would add "mousefood" to keywords instead.
Also no-std in both keywords and categories.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I removed exclude, and changed it to this:

keywords = ["mousefood", "ratatui", "tui"]
categories = ["no-std", "graphics"]


[dependencies]
indoc = "2"
itertools = { version = "0.14", default-features = false }
ratatui-core.workspace = true
5 changes: 5 additions & 0 deletions mousefood-extras/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// TODO: should this be here? even for `std` builds?
#![no_std]

mod logo;
pub use logo::MouseFoodLogo;
104 changes: 104 additions & 0 deletions mousefood-extras/src/logo.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
use itertools::Itertools;
use ratatui_core::buffer::Buffer;
use ratatui_core::layout::Rect;
use ratatui_core::style::Color;
use ratatui_core::widgets::Widget;

const MOUSEFOOD_LOGO: &str = indoc::indoc! {"
abccccccc
dddd ddd d d ddddd ddeebbbbbbbacc
d d d d d d d d d babbbcaaccc
d d d d d d d ddddd eee abbbbabccc
d d d d d d d e e bbabbbbbbccc
d d d ddd ddd deeee eebbbbbbbbbcccc
bbbcabbbbcccbcc
ddddd ddd ddd eeee bbbcaabbbccccbac
d d d d e e e bbbbabbbbccccccc
ddd d d e e e ebaabbbcaacccbcccc
d d e e e e e abbbbbabcccbcc
d dde eeeb eeee aabbbbbcbccabc
abc b bbbbccacccc
"};

const EMPTY: char = ' ';
const LIGHT_TEXT: char = 'd';
const DARK_TEXT: char = 'e';
const LIGHT_CHEESE: char = 'c';
const MIDDLE_CHEESE: char = 'b';
const DARK_CHEESE: char = 'a';
const TERM: char = '░';
const TERM_BORDER: char = '▒';
const TERM_CURSOR: char = '▓';

#[derive(Default)]
pub struct MouseFoodLogo {}

impl MouseFoodLogo {
pub fn new() -> Self {
Self::default()
}

const fn color_for(&self, c: char) -> Option<Color> {
match c {
LIGHT_TEXT => Some(Color::Rgb(139, 151, 182)),
DARK_TEXT => Some(Color::Rgb(53, 54, 88)),
LIGHT_CHEESE => Some(Color::Rgb(236, 233, 16)),
MIDDLE_CHEESE => Some(Color::Rgb(236, 171, 17)),
DARK_CHEESE => Some(Color::Rgb(239, 110, 16)),
TERM => Some(Color::Indexed(232)),
TERM_BORDER => Some(Color::Indexed(237)),
TERM_CURSOR => Some(Color::Indexed(248)),
_ => None,
}
}
}

impl Widget for MouseFoodLogo {
fn render(self, area: Rect, buf: &mut Buffer) {
let area = area.intersection(buf.area);
if area.is_empty() {
return;
}

for (y, (line1, line2)) in MOUSEFOOD_LOGO.lines().tuples().enumerate() {
for (x, (ch1, ch2)) in line1.chars().zip(line2.chars()).enumerate() {
let x = area.left() + x as u16;
let y = area.top() + y as u16;

// Check if coordinates are within the buffer area
if x >= area.right() || y >= area.bottom() {
continue;
}

let cell = &mut buf[(x, y)];
// given two cells which make up the top and bottom of the character,
// Foreground color should be the non-space, non-terminal
let (fg, bg) = match (ch1, ch2) {
(EMPTY, EMPTY) => (None, None),
(c, EMPTY) | (EMPTY, c) => (self.color_for(c), None),
(TERM, TERM_BORDER) => (self.color_for(TERM_BORDER), self.color_for(TERM)),
(TERM, c) | (c, TERM) => (self.color_for(c), self.color_for(TERM)),
(c1, c2) => (self.color_for(c1), self.color_for(c2)),
};
// symbol should make the empty space or terminal bg as the empty part of the block
let symbol = match (ch1, ch2) {
(EMPTY, EMPTY) => None,
(TERM, TERM) => Some(EMPTY),
(_, EMPTY | TERM) => Some('▀'),
(EMPTY | TERM, _) => Some('▄'),
(c, d) if c == d => Some('█'),
(_, _) => Some('▀'),
};
if let Some(fg) = fg {
cell.fg = fg;
}
if let Some(bg) = bg {
cell.bg = bg;
}
if let Some(symb) = symbol {
cell.set_char(symb);
}
}
}
}
}