From 8d2fec7873e5e4697b77ba1cb04e3b33c66625c5 Mon Sep 17 00:00:00 2001 From: "Tate, Hongliang Tian" Date: Tue, 9 Sep 2025 09:41:40 +0800 Subject: [PATCH] Introduce ASCII art representations of the Asterinas logo --- Cargo.lock | 14 ++- Cargo.toml | 1 + Makefile | 3 +- kernel/Cargo.toml | 1 + kernel/libs/logo-ascii-art/Cargo.toml | 20 ++++ kernel/libs/logo-ascii-art/README.md | 7 ++ kernel/libs/logo-ascii-art/src/lib.rs | 46 +++++++++ .../logo-ascii-art/src/logo_ascii_art.txt | 24 +++++ .../src/logo_ascii_art_gradient.txt | 24 +++++ kernel/libs/logo-ascii-art/src/main.rs | 99 +++++++++++++++++++ kernel/src/lib.rs | 12 +-- 11 files changed, 237 insertions(+), 14 deletions(-) create mode 100644 kernel/libs/logo-ascii-art/Cargo.toml create mode 100644 kernel/libs/logo-ascii-art/README.md create mode 100644 kernel/libs/logo-ascii-art/src/lib.rs create mode 100644 kernel/libs/logo-ascii-art/src/logo_ascii_art.txt create mode 100644 kernel/libs/logo-ascii-art/src/logo_ascii_art_gradient.txt create mode 100644 kernel/libs/logo-ascii-art/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 1f54d43a8..0da2cb7dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,6 +232,7 @@ dependencies = [ "lending-iterator", "libflate", "log", + "logo-ascii-art", "loongArch64", "lru", "osdk-frame-allocator", @@ -1104,6 +1105,13 @@ version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +[[package]] +name = "logo-ascii-art" +version = "0.1.0" +dependencies = [ + "owo-colors 4.2.2", +] + [[package]] name = "loongArch64" version = "0.2.5" @@ -1270,7 +1278,7 @@ name = "osdk-test-kernel" version = "0.16.0" dependencies = [ "ostd", - "owo-colors 4.2.0", + "owo-colors 4.2.2", ] [[package]] @@ -1351,9 +1359,9 @@ checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f" [[package]] name = "owo-colors" -version = "4.2.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" +checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" [[package]] name = "paste" diff --git a/Cargo.toml b/Cargo.toml index be13d3320..6861d4970 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ members = [ "kernel/libs/aster-bigtcp", "kernel/libs/jhash", "kernel/libs/keyable-arc", + "kernel/libs/logo-ascii-art", "kernel/libs/typeflags", "kernel/libs/typeflags-util", "kernel/libs/atomic-integer-wrapper", diff --git a/Makefile b/Makefile index 19e63b994..cf7b19e79 100644 --- a/Makefile +++ b/Makefile @@ -183,7 +183,8 @@ NON_OSDK_CRATES := \ kernel/libs/keyable-arc \ kernel/libs/typeflags \ kernel/libs/typeflags-util \ - kernel/libs/atomic-integer-wrapper + kernel/libs/atomic-integer-wrapper \ + kernel/libs/logo-ascii-art # In contrast, OSDK crates depend on OSTD (or being `ostd` itself) # and need to be built or tested with OSDK. diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 2c9ca8e05..0ee17b047 100644 --- a/kernel/Cargo.toml +++ b/kernel/Cargo.toml @@ -22,6 +22,7 @@ aster-systree = { path = "comps/systree" } aster-keyboard = { path = "comps/keyboard" } component = { path = "libs/comp-sys/component" } controlled = { path = "libs/comp-sys/controlled" } +logo-ascii-art = { path = "libs/logo-ascii-art" } osdk-frame-allocator = { path = "../osdk/deps/frame-allocator" } osdk-heap-allocator = { path = "../osdk/deps/heap-allocator" } ostd = { path = "../ostd" } diff --git a/kernel/libs/logo-ascii-art/Cargo.toml b/kernel/libs/logo-ascii-art/Cargo.toml new file mode 100644 index 000000000..8f772fde3 --- /dev/null +++ b/kernel/libs/logo-ascii-art/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "logo-ascii-art" +version = "0.1.0" +edition = "2024" + +[dependencies] +# This crate is only needed by `main.rs`, not `lib.rs` +owo-colors = { version = "4.2.2", optional = true } + +[features] +default = [] +color = ["owo-colors"] + +[[bin]] +name = "logo-ascii-art" +path = "src/main.rs" +required-features = ["color"] + +[lints] +workspace = true diff --git a/kernel/libs/logo-ascii-art/README.md b/kernel/libs/logo-ascii-art/README.md new file mode 100644 index 000000000..a2fe88b33 --- /dev/null +++ b/kernel/libs/logo-ascii-art/README.md @@ -0,0 +1,7 @@ +# logo-ascii-art + +This crate provides ASCII art representations of the Asterinas logo. + +The ASCII art are offered as two static string slices containing the logo: +* A classic black-and-white version; and +* A vibrant, gradient-colored one, suitable for splash screens or command-line tool branding. diff --git a/kernel/libs/logo-ascii-art/src/lib.rs b/kernel/libs/logo-ascii-art/src/lib.rs new file mode 100644 index 000000000..288d7717f --- /dev/null +++ b/kernel/libs/logo-ascii-art/src/lib.rs @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MPL-2.0 + +//! Provides ASCII art representations of the Asterinas logo. +//! +//! This crate offers two static string slices containing the logo: +//! a classic black-and-white version and +//! a vibrant, gradient-colored one, +//! suitable for splash screens or command-line tool branding. + +#![no_std] + +/// Returns the ASCII art of the Asterinas logo in black and white. +/// +/// ## Generation +/// +/// The ASCII art was generated using the online tool at +/// [asciiart.eu](https://www.asciiart.eu/image-to-ascii). +pub fn get_black_white_version() -> &'static str { + // The ASCII art is generated using an online tool: + // https://www.asciiart.eu/image-to-ascii + static LOGO_ASCII_ART: &str = include_str!("logo_ascii_art.txt"); + LOGO_ASCII_ART +} + +/// Returns the ASCII art of the Asterinas logo with gradient colors. +/// +/// The colors are represented using ANSI escape codes, +/// so this version must be viewed in a terminal. +/// +/// ## Generation +/// +/// This version is generated by the CLI version of this crate. +/// To regenerate it, run the following command: +/// +/// ```sh +/// cd logo-ascii-art/ +/// cargo run --features=color > src/logo_ascii_art_gradient.txt +/// ``` +pub fn get_gradient_color_version() -> &'static str { + // The gradient color version is generated by running: + // ``` + // cd logo_ascii_art && cargo run > src/logo_ascii_art_gradient.txt + // ``` + static LOGO_ASCII_ART: &str = include_str!("logo_ascii_art_gradient.txt"); + LOGO_ASCII_ART +} diff --git a/kernel/libs/logo-ascii-art/src/logo_ascii_art.txt b/kernel/libs/logo-ascii-art/src/logo_ascii_art.txt new file mode 100644 index 000000000..8724faa9b --- /dev/null +++ b/kernel/libs/logo-ascii-art/src/logo_ascii_art.txt @@ -0,0 +1,24 @@ + ...... + .-++++=: + .=+++++=: + :+++++++=: + .-++++++++=. + .=**++==+++=. + :****+-.=+++=. + .=****+: .++++=. + .+****=. .++++- + .-*****=. :++++- + .::-=============+*****+-----=++++=-:::::::. + ..:-*#########*********+++++++=======:. + .:+*#####****+++++++++++=====-.. + ..-+#******=.. -++++. + -+=...:*******=..=++++. + .+*+++=. ..=*****+-=++++. + .:***+=.. .-+**++++++=. + .-***+: .-+++++++= + .*#*=. .=+++++= + .-*#+.. .:=+++- + .=#=. .=++- + :*=. ... + .:-. Presented by the Asterinas developers + .. Released under Mozilla Public License v2.0 \ No newline at end of file diff --git a/kernel/libs/logo-ascii-art/src/logo_ascii_art_gradient.txt b/kernel/libs/logo-ascii-art/src/logo_ascii_art_gradient.txt new file mode 100644 index 000000000..ee465651b --- /dev/null +++ b/kernel/libs/logo-ascii-art/src/logo_ascii_art_gradient.txt @@ -0,0 +1,24 @@ + ...... + .-++++=: + .=+++++=: + :+++++++=: + .-++++++++=. + .=**++==+++=. + :****+-.=+++=. + .=****+: .++++=. + .+****=. .++++- + .-*****=. :++++- + .::-=============+*****+-----=++++=-:::::::. + ..:-*#########*********+++++++=======:. + .:+*#####****+++++++++++=====-.. + ..-+#******=.. -++++. + -+=...:*******=..=++++. + .+*+++=. ..=*****+-=++++. + .:***+=.. .-+**++++++=. + .-***+: .-+++++++= + .*#*=. .=+++++= + .-*#+.. .:=+++- + .=#=. .=++- + :*=. ... + .:-. Presented by the Asterinas developers + .. Released under Mozilla Public License v2.0 diff --git a/kernel/libs/logo-ascii-art/src/main.rs b/kernel/libs/logo-ascii-art/src/main.rs new file mode 100644 index 000000000..c60035fdd --- /dev/null +++ b/kernel/libs/logo-ascii-art/src/main.rs @@ -0,0 +1,99 @@ +// SPDX-License-Identifier: MPL-2.0 + +use logo_ascii_art::get_black_white_version; + +/// Generates the ASCII art of the Asterinas logo in gradient colors. +/// +/// The gradient-color version is generated +/// by applying a horizontal gradient color transformation +/// on the black-and-white version. +fn gen_gradient_color_version() -> String { + use owo_colors::{Rgb, *}; + + let start_gradient_color = Rgb(33, 54, 245); + let end_gradient_color = Rgb(113, 240, 252); + let colored_logo = apply_gradient( + get_black_white_version(), + start_gradient_color, + end_gradient_color, + ); + return colored_logo; + + /// Applies a horizontal gradient color transformation to ASCII art. + /// + /// This function takes a string of ASCII art and + /// two `Rgb` color values representing the start and end colors of the gradient. + /// The function returns a new string of the ASCII art with the gradient colors applied. + /// + /// The gradient is applied horizontally. + /// The leftmost, non-whitespace character will be colored with `start_color`, + /// and the rightmost, non-whitespace character will be colored with `end_color`. + /// All non-whitespace characters between the leftmost and the rightmost ones + /// will be colored based on its column position, + /// interpolating between the `start_color` and `end_color` linearly. + fn apply_gradient(ascii_art: &str, start_color: Rgb, end_color: Rgb) -> String { + let lines: Vec<&str> = ascii_art.lines().collect(); + if lines.is_empty() { + return String::new(); + } + + let interpolate = |col| -> Rgb { + let min_col = lines + .iter() + .flat_map(|line| line.char_indices()) + .filter(|(_, c)| !c.is_whitespace()) + .map(|(idx, _)| idx) + .min() + .unwrap_or(0); + + let max_col = lines + .iter() + .flat_map(|line| line.char_indices()) + .filter(|(_, c)| !c.is_whitespace()) + .map(|(idx, _)| idx) + .max() + .unwrap_or(0); + + // Unexpected logo ASCII art! + assert!(min_col != max_col); + + if col < min_col { + return start_color; + } + if col > max_col { + return end_color; + } + + let r = start_color.0 as f32 + + (end_color.0 as f32 - start_color.0 as f32) * (col - min_col) as f32 + / (max_col - min_col) as f32; + let g = start_color.1 as f32 + + (end_color.1 as f32 - start_color.1 as f32) * (col - min_col) as f32 + / (max_col - min_col) as f32; + let b = start_color.2 as f32 + + (end_color.2 as f32 - start_color.2 as f32) * (col - min_col) as f32 + / (max_col - min_col) as f32; + + Rgb(r as u8, g as u8, b as u8) + }; + + let mut result = String::new(); + for line in &lines { + for (col, ch) in line.chars().enumerate() { + if ch.is_whitespace() { + result.push(ch); + } else { + let color = interpolate(col); + result.push_str(&ch.color(color).to_string()); + } + } + result.push('\n'); + } + + result + } +} + +fn main() { + print!("{}", gen_gradient_color_version()); +} diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 63cded977..134c1514d 100644 --- a/kernel/src/lib.rs +++ b/kernel/src/lib.rs @@ -186,14 +186,6 @@ fn first_kthread() { } fn print_banner() { - println!("\x1B[36m"); - println!( - r" - _ ___ _____ ___ ___ ___ _ _ _ ___ - /_\ / __|_ _| __| _ \_ _| \| | /_\ / __| - / _ \\__ \ | | | _|| /| || .` |/ _ \\__ \ -/_/ \_\___/ |_| |___|_|_\___|_|\_/_/ \_\___/ -" - ); - println!("\x1B[0m"); + println!(""); + println!("{}", logo_ascii_art::get_gradient_color_version()); }