mirror of
https://github.com/ratatui-org/ratatui
synced 2024-11-25 22:20:31 +00:00
chore: replace big_text with hardcoded logo (#1203)
big_text.rs was a copy of the code from tui-big-text and was getting gradually out of sync with the original crate. It was also rendering something a bit different than the Ratatui logo. This commit replaces the big_text.rs file with a much smaller string representation of the Ratatui logo. ![demo2](https://raw.githubusercontent.com/ratatui-org/ratatui/images/examples/demo2-destroy.gif)
This commit is contained in:
parent
a80a8a6a47
commit
edc2af9822
4 changed files with 16 additions and 861 deletions
|
@ -1,841 +0,0 @@
|
||||||
//! [tui-big-text] is a rust crate that renders large pixel text as a [Ratatui] widget using the
|
|
||||||
//! glyphs from the [font8x8] crate.
|
|
||||||
//!
|
|
||||||
//! ![Hello World example](https://vhs.charm.sh/vhs-2UxNc2SJgiNqHoowbsXAMW.gif)
|
|
||||||
//!
|
|
||||||
//! # Installation
|
|
||||||
//!
|
|
||||||
//! ```shell
|
|
||||||
//! cargo add ratatui tui-big-text
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! # Usage
|
|
||||||
//!
|
|
||||||
//! Create a [`BigText`] widget using `BigTextBuilder` and pass it to [`Frame::render_widget`] to
|
|
||||||
//! render be rendered. The builder allows you to customize the [`Style`] of the widget and the
|
|
||||||
//! [`PixelSize`] of the glyphs. The [`PixelSize`] can be used to control how many character cells
|
|
||||||
//! are used to represent a single pixel of the 8x8 font.
|
|
||||||
//!
|
|
||||||
//! # Example
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use anyhow::Result;
|
|
||||||
//! use ratatui::{
|
|
||||||
//! backend::{self, Backend, CrosstermBackend},
|
|
||||||
//! buffer::{self, Buffer},
|
|
||||||
//! layout::{self, Alignment, Constraint, Direction, Layout, Margin, Rect},
|
|
||||||
//! style::{self, Color, Modifier, Style, Styled, Stylize},
|
|
||||||
//! symbols::{self, Marker},
|
|
||||||
//! text::{self, Line, Masked, Span, Text},
|
|
||||||
//! widgets::{block::BlockExt, StatefulWidget, Widget},
|
|
||||||
//! CompletedFrame, Frame, Terminal, TerminalOptions, Viewport,
|
|
||||||
//! };
|
|
||||||
//! use tui_big_text::{BigTextBuilder, PixelSize};
|
|
||||||
//!
|
|
||||||
//! fn render(frame: &mut Frame) -> Result<()> {
|
|
||||||
//! let big_text = BigTextBuilder::default()
|
|
||||||
//! .pixel_size(PixelSize::Full)
|
|
||||||
//! .style(Style::new().blue())
|
|
||||||
//! .lines(vec![
|
|
||||||
//! "Hello".red().into(),
|
|
||||||
//! "World".white().into(),
|
|
||||||
//! "~~~~~".into(),
|
|
||||||
//! ])
|
|
||||||
//! .build()?;
|
|
||||||
//! frame.render_widget(big_text, frame.size());
|
|
||||||
//! Ok(())
|
|
||||||
//! }
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! [tui-big-text]: https://crates.io/crates/tui-big-text
|
|
||||||
//! [Ratatui]: https://crates.io/crates/ratatui
|
|
||||||
//! [font8x8]: https://crates.io/crates/font8x8
|
|
||||||
//! [`BigText`]: crate::BigText
|
|
||||||
//! [`PixelSize`]: crate::PixelSize
|
|
||||||
//! [`Frame::render_widget`]: ratatui::Frame::render_widget
|
|
||||||
//! [`Style`]: ratatui::style::Style
|
|
||||||
|
|
||||||
use std::cmp::min;
|
|
||||||
|
|
||||||
use derive_builder::Builder;
|
|
||||||
use font8x8::UnicodeFonts;
|
|
||||||
use ratatui::{
|
|
||||||
buffer::Buffer,
|
|
||||||
layout::Rect,
|
|
||||||
style::Style,
|
|
||||||
text::{Line, StyledGrapheme},
|
|
||||||
widgets::Widget,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[allow(unused)]
|
|
||||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Default)]
|
|
||||||
pub enum PixelSize {
|
|
||||||
#[default]
|
|
||||||
/// A pixel from the 8x8 font is represented by a full character cell in the terminal.
|
|
||||||
Full,
|
|
||||||
/// A pixel from the 8x8 font is represented by a half (upper/lower) character cell in the
|
|
||||||
/// terminal.
|
|
||||||
HalfHeight,
|
|
||||||
/// A pixel from the 8x8 font is represented by a half (left/right) character cell in the
|
|
||||||
/// terminal.
|
|
||||||
HalfWidth,
|
|
||||||
/// A pixel from the 8x8 font is represented by a quadrant of a character cell in the terminal.
|
|
||||||
Quadrant,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Displays one or more lines of text using 8x8 pixel characters.
|
|
||||||
///
|
|
||||||
/// The text is rendered using the [font8x8](https://crates.io/crates/font8x8) crate.
|
|
||||||
///
|
|
||||||
/// Using the `pixel_size` method, you can also chose, how 'big' a pixel should be.
|
|
||||||
/// Currently a pixel of the 8x8 font can be represented by one full or half
|
|
||||||
/// (horizontal/vertical/both) character cell of the terminal.
|
|
||||||
///
|
|
||||||
/// # Examples
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use ratatui::{
|
|
||||||
/// backend::{self, Backend, CrosstermBackend},
|
|
||||||
/// buffer::{self, Buffer},
|
|
||||||
/// layout::{self, Alignment, Constraint, Direction, Layout, Margin, Rect},
|
|
||||||
/// style::{self, Color, Modifier, Style, Styled, Stylize},
|
|
||||||
/// symbols::{self, Marker},
|
|
||||||
/// text::{self, Line, Masked, Span, Text},
|
|
||||||
/// widgets::{block::BlockExt, StatefulWidget, Widget},
|
|
||||||
/// CompletedFrame, Frame, Terminal, TerminalOptions, Viewport,
|
|
||||||
/// };
|
|
||||||
/// use tui_big_text::{BigTextBuilder, PixelSize};
|
|
||||||
///
|
|
||||||
/// BigText::builder()
|
|
||||||
/// .pixel_size(PixelSize::Full)
|
|
||||||
/// .style(Style::new().white())
|
|
||||||
/// .lines(vec![
|
|
||||||
/// "Hello".red().into(),
|
|
||||||
/// "World".blue().into(),
|
|
||||||
/// "=====".into(),
|
|
||||||
/// ])
|
|
||||||
/// .build();
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Renders:
|
|
||||||
///
|
|
||||||
/// ```plain
|
|
||||||
/// ██ ██ ███ ███
|
|
||||||
/// ██ ██ ██ ██
|
|
||||||
/// ██ ██ ████ ██ ██ ████
|
|
||||||
/// ██████ ██ ██ ██ ██ ██ ██
|
|
||||||
/// ██ ██ ██████ ██ ██ ██ ██
|
|
||||||
/// ██ ██ ██ ██ ██ ██ ██
|
|
||||||
/// ██ ██ ████ ████ ████ ████
|
|
||||||
///
|
|
||||||
/// ██ ██ ███ ███
|
|
||||||
/// ██ ██ ██ ██
|
|
||||||
/// ██ ██ ████ ██ ███ ██ ██
|
|
||||||
/// ██ █ ██ ██ ██ ███ ██ ██ █████
|
|
||||||
/// ███████ ██ ██ ██ ██ ██ ██ ██
|
|
||||||
/// ███ ███ ██ ██ ██ ██ ██ ██
|
|
||||||
/// ██ ██ ████ ████ ████ ███ ██
|
|
||||||
///
|
|
||||||
/// ███ ██ ███ ██ ███ ██ ███ ██ ███ ██
|
|
||||||
/// ██ ███ ██ ███ ██ ███ ██ ███ ██ ███
|
|
||||||
/// ```
|
|
||||||
#[derive(Debug, Builder, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub struct BigText<'a> {
|
|
||||||
/// The text to display
|
|
||||||
#[builder(setter(into))]
|
|
||||||
lines: Vec<Line<'a>>,
|
|
||||||
|
|
||||||
/// The style of the widget
|
|
||||||
///
|
|
||||||
/// Defaults to `Style::default()`
|
|
||||||
#[builder(default)]
|
|
||||||
style: Style,
|
|
||||||
|
|
||||||
/// The size of single glyphs
|
|
||||||
///
|
|
||||||
/// Defaults to `BigTextSize::default()` (=> `BigTextSize::Full`)
|
|
||||||
#[builder(default)]
|
|
||||||
pixel_size: PixelSize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Widget for BigText<'_> {
|
|
||||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
|
||||||
let layout = layout(area, self.pixel_size);
|
|
||||||
for (line, line_layout) in self.lines.iter().zip(layout) {
|
|
||||||
for (g, cell) in line.styled_graphemes(self.style).zip(line_layout) {
|
|
||||||
render_symbol(&g, cell, buf, self.pixel_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns how many cells are needed to display a full 8x8 glyphe using the given font size
|
|
||||||
const fn cells_per_glyph(size: PixelSize) -> (u16, u16) {
|
|
||||||
match size {
|
|
||||||
PixelSize::Full => (8, 8),
|
|
||||||
PixelSize::HalfHeight => (8, 4),
|
|
||||||
PixelSize::HalfWidth => (4, 8),
|
|
||||||
PixelSize::Quadrant => (4, 4),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Chunk the area into as many x*y cells as possible returned as a 2D iterator of `Rect`s
|
|
||||||
/// representing the rows of cells.
|
|
||||||
/// The size of each cell depends on given font size
|
|
||||||
fn layout(
|
|
||||||
area: Rect,
|
|
||||||
pixel_size: PixelSize,
|
|
||||||
) -> impl IntoIterator<Item = impl IntoIterator<Item = Rect>> {
|
|
||||||
let (width, height) = cells_per_glyph(pixel_size);
|
|
||||||
(area.top()..area.bottom())
|
|
||||||
.step_by(height as usize)
|
|
||||||
.map(move |y| {
|
|
||||||
(area.left()..area.right())
|
|
||||||
.step_by(width as usize)
|
|
||||||
.map(move |x| {
|
|
||||||
let width = min(area.right() - x, width);
|
|
||||||
let height = min(area.bottom() - y, height);
|
|
||||||
Rect::new(x, y, width, height)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a single grapheme into a cell by looking up the corresponding 8x8 bitmap in the
|
|
||||||
/// `BITMAPS` array and setting the corresponding cells in the buffer.
|
|
||||||
fn render_symbol(grapheme: &StyledGrapheme, area: Rect, buf: &mut Buffer, pixel_size: PixelSize) {
|
|
||||||
buf.set_style(area, grapheme.style);
|
|
||||||
let c = grapheme.symbol.chars().next().unwrap(); // TODO: handle multi-char graphemes
|
|
||||||
if let Some(glyph) = font8x8::BASIC_FONTS.get(c) {
|
|
||||||
render_glyph(glyph, area, buf, pixel_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the correct unicode symbol for two vertical "pixels"
|
|
||||||
const fn get_symbol_half_height(top: u8, bottom: u8) -> char {
|
|
||||||
match top {
|
|
||||||
0 => match bottom {
|
|
||||||
0 => ' ',
|
|
||||||
_ => '▄',
|
|
||||||
},
|
|
||||||
_ => match bottom {
|
|
||||||
0 => '▀',
|
|
||||||
_ => '█',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the correct unicode symbol for two horizontal "pixels"
|
|
||||||
const fn get_symbol_half_width(left: u8, right: u8) -> char {
|
|
||||||
match left {
|
|
||||||
0 => match right {
|
|
||||||
0 => ' ',
|
|
||||||
_ => '▐',
|
|
||||||
},
|
|
||||||
_ => match right {
|
|
||||||
0 => '▌',
|
|
||||||
_ => '█',
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the correct unicode symbol for 2x2 "pixels"
|
|
||||||
const fn get_symbol_half_size(
|
|
||||||
top_left: u8,
|
|
||||||
top_right: u8,
|
|
||||||
bottom_left: u8,
|
|
||||||
bottom_right: u8,
|
|
||||||
) -> char {
|
|
||||||
const QUADRANT_SYMBOLS: [char; 16] = [
|
|
||||||
' ', '▘', '▝', '▀', '▖', '▌', '▞', '▛', '▗', '▚', '▐', '▜', '▄', '▙', '▟', '█',
|
|
||||||
];
|
|
||||||
|
|
||||||
let top_left = if top_left > 0 { 1 } else { 0 };
|
|
||||||
let top_right = if top_right > 0 { 1 << 1 } else { 0 };
|
|
||||||
let bottom_left = if bottom_left > 0 { 1 << 2 } else { 0 };
|
|
||||||
let bottom_right = if bottom_right > 0 { 1 << 3 } else { 0 };
|
|
||||||
|
|
||||||
QUADRANT_SYMBOLS[top_left + top_right + bottom_left + bottom_right]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a single 8x8 glyph into a cell by setting the corresponding cells in the buffer.
|
|
||||||
fn render_glyph(glyph: [u8; 8], area: Rect, buf: &mut Buffer, pixel_size: PixelSize) {
|
|
||||||
let (width, height) = cells_per_glyph(pixel_size);
|
|
||||||
|
|
||||||
let glyph_vertical_index = (0..glyph.len()).step_by(8 / height as usize);
|
|
||||||
let glyph_horizontal_bit_selector = (0..8).step_by(8 / width as usize);
|
|
||||||
|
|
||||||
for (row, y) in glyph_vertical_index.zip(area.top()..area.bottom()) {
|
|
||||||
for (col, x) in glyph_horizontal_bit_selector
|
|
||||||
.clone()
|
|
||||||
.zip(area.left()..area.right())
|
|
||||||
{
|
|
||||||
let cell = buf.get_mut(x, y);
|
|
||||||
let symbol_character = match pixel_size {
|
|
||||||
PixelSize::Full => match glyph[row] & (1 << col) {
|
|
||||||
0 => ' ',
|
|
||||||
_ => '█',
|
|
||||||
},
|
|
||||||
PixelSize::HalfHeight => {
|
|
||||||
let top = glyph[row] & (1 << col);
|
|
||||||
let bottom = glyph[row + 1] & (1 << col);
|
|
||||||
get_symbol_half_height(top, bottom)
|
|
||||||
}
|
|
||||||
PixelSize::HalfWidth => {
|
|
||||||
let left = glyph[row] & (1 << col);
|
|
||||||
let right = glyph[row] & (1 << (col + 1));
|
|
||||||
get_symbol_half_width(left, right)
|
|
||||||
}
|
|
||||||
PixelSize::Quadrant => {
|
|
||||||
let top_left = glyph[row] & (1 << col);
|
|
||||||
let top_right = glyph[row] & (1 << (col + 1));
|
|
||||||
let bottom_left = glyph[row + 1] & (1 << col);
|
|
||||||
let bottom_right = glyph[row + 1] & (1 << (col + 1));
|
|
||||||
get_symbol_half_size(top_left, top_right, bottom_left, bottom_right)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
cell.set_char(symbol_character);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use ratatui::style::Stylize;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn build() -> Result<()> {
|
|
||||||
let lines = vec![Line::from(vec!["Hello".red(), "World".blue()])];
|
|
||||||
let style = Style::new().green();
|
|
||||||
let pixel_size = PixelSize::default();
|
|
||||||
assert_eq!(
|
|
||||||
BigTextBuilder::default()
|
|
||||||
.lines(lines.clone())
|
|
||||||
.style(style)
|
|
||||||
.build()?,
|
|
||||||
BigText {
|
|
||||||
lines,
|
|
||||||
style,
|
|
||||||
pixel_size
|
|
||||||
}
|
|
||||||
);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_single_line() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.lines(vec![Line::from("SingleLine")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 80, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
" ████ ██ ███ ████ ██ ",
|
|
||||||
"██ ██ ██ ██ ",
|
|
||||||
"███ ███ █████ ███ ██ ██ ████ ██ ███ █████ ████ ",
|
|
||||||
" ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
" ███ ██ ██ ██ ██ ██ ██ ██████ ██ █ ██ ██ ██ ██████ ",
|
|
||||||
"██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
" ████ ████ ██ ██ ██ ████ ████ ███████ ████ ██ ██ ████ ",
|
|
||||||
" █████ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_truncated() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.lines(vec![Line::from("Truncated")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 70, 6));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"██████ █ ███",
|
|
||||||
"█ ██ █ ██ ██",
|
|
||||||
" ██ ██ ███ ██ ██ █████ ████ ████ █████ ████ ██",
|
|
||||||
" ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██████ ██ ██",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █ ██ ██ ██",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_multiple_lines() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.lines(vec![Line::from("Multi"), Line::from("Lines")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 16));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"██ ██ ███ █ ██ ",
|
|
||||||
"███ ███ ██ ██ ",
|
|
||||||
"███████ ██ ██ ██ █████ ███ ",
|
|
||||||
"███████ ██ ██ ██ ██ ██ ",
|
|
||||||
"██ █ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
"██ ██ ██ ██ ██ ██ █ ██ ",
|
|
||||||
"██ ██ ███ ██ ████ ██ ████ ",
|
|
||||||
" ",
|
|
||||||
"████ ██ ",
|
|
||||||
" ██ ",
|
|
||||||
" ██ ███ █████ ████ █████ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
" ██ █ ██ ██ ██ ██████ ████ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
"███████ ████ ██ ██ ████ █████ ",
|
|
||||||
" ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_widget_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.lines(vec![Line::from("Styled")])
|
|
||||||
.style(Style::new().bold())
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 48, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
" ████ █ ███ ███ ".bold(),
|
|
||||||
"██ ██ ██ ██ ██ ".bold(),
|
|
||||||
"███ █████ ██ ██ ██ ████ ██ ".bold(),
|
|
||||||
" ███ ██ ██ ██ ██ ██ ██ █████ ".bold(),
|
|
||||||
" ███ ██ ██ ██ ██ ██████ ██ ██ ".bold(),
|
|
||||||
"██ ██ ██ █ █████ ██ ██ ██ ██ ".bold(),
|
|
||||||
" ████ ██ ██ ████ ████ ███ ██ ".bold(),
|
|
||||||
" █████ ".bold(),
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_line_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.lines(vec![
|
|
||||||
Line::from("Red".red()),
|
|
||||||
Line::from("Green".green()),
|
|
||||||
Line::from("Blue".blue()),
|
|
||||||
])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 24));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let mut expected = Buffer::with_lines([
|
|
||||||
"██████ ███ ",
|
|
||||||
" ██ ██ ██ ",
|
|
||||||
" ██ ██ ████ ██ ",
|
|
||||||
" █████ ██ ██ █████ ",
|
|
||||||
" ██ ██ ██████ ██ ██ ",
|
|
||||||
" ██ ██ ██ ██ ██ ",
|
|
||||||
"███ ██ ████ ███ ██ ",
|
|
||||||
" ",
|
|
||||||
" ████ ",
|
|
||||||
" ██ ██ ",
|
|
||||||
"██ ██ ███ ████ ████ █████ ",
|
|
||||||
"██ ███ ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
"██ ███ ██ ██ ██████ ██████ ██ ██ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ██ ",
|
|
||||||
" █████ ████ ████ ████ ██ ██ ",
|
|
||||||
" ",
|
|
||||||
"██████ ███ ",
|
|
||||||
" ██ ██ ██ ",
|
|
||||||
" ██ ██ ██ ██ ██ ████ ",
|
|
||||||
" █████ ██ ██ ██ ██ ██ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██████ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██ ",
|
|
||||||
"██████ ████ ███ ██ ████ ",
|
|
||||||
" ",
|
|
||||||
]);
|
|
||||||
expected.set_style(Rect::new(0, 0, 24, 8), Style::new().red());
|
|
||||||
expected.set_style(Rect::new(0, 8, 40, 8), Style::new().green());
|
|
||||||
expected.set_style(Rect::new(0, 16, 32, 8), Style::new().blue());
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_height_single_line() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfHeight)
|
|
||||||
.lines(vec![Line::from("SingleLine")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 80, 4));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▄█▀▀█▄ ▀▀ ▀██ ▀██▀ ▀▀ ",
|
|
||||||
"▀██▄ ▀██ ██▀▀█▄ ▄█▀▀▄█▀ ██ ▄█▀▀█▄ ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ",
|
|
||||||
"▄▄ ▀██ ██ ██ ██ ▀█▄▄██ ██ ██▀▀▀▀ ██ ▄█ ██ ██ ██ ██▀▀▀▀ ",
|
|
||||||
" ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_height_truncated() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfHeight)
|
|
||||||
.lines(vec![Line::from("Truncated")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 70, 3));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"█▀██▀█ ▄█ ▀██",
|
|
||||||
" ██ ▀█▄█▀█▄ ██ ██ ██▀▀█▄ ▄█▀▀█▄ ▀▀▀█▄ ▀██▀▀ ▄█▀▀█▄ ▄▄▄██",
|
|
||||||
" ██ ██ ▀▀ ██ ██ ██ ██ ██ ▄▄ ▄█▀▀██ ██ ▄ ██▀▀▀▀ ██ ██",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_height_multiple_lines() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfHeight)
|
|
||||||
.lines(vec![Line::from("Multi"), Line::from("Lines")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"██▄ ▄██ ▀██ ▄█ ▀▀ ",
|
|
||||||
"███████ ██ ██ ██ ▀██▀▀ ▀██ ",
|
|
||||||
"██ ▀ ██ ██ ██ ██ ██ ▄ ██ ",
|
|
||||||
"▀▀ ▀▀ ▀▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀▀▀ ",
|
|
||||||
"▀██▀ ▀▀ ",
|
|
||||||
" ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ▄█▀▀▀▀ ",
|
|
||||||
" ██ ▄█ ██ ██ ██ ██▀▀▀▀ ▀▀▀█▄ ",
|
|
||||||
"▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀▀▀▀ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_height_widget_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfHeight)
|
|
||||||
.lines(vec![Line::from("Styled")])
|
|
||||||
.style(Style::new().bold())
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 48, 4));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▄█▀▀█▄ ▄█ ▀██ ▀██ ".bold(),
|
|
||||||
"▀██▄ ▀██▀▀ ██ ██ ██ ▄█▀▀█▄ ▄▄▄██ ".bold(),
|
|
||||||
"▄▄ ▀██ ██ ▄ ▀█▄▄██ ██ ██▀▀▀▀ ██ ██ ".bold(),
|
|
||||||
" ▀▀▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ".bold(),
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_height_line_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfHeight)
|
|
||||||
.lines(vec![
|
|
||||||
Line::from("Red".red()),
|
|
||||||
Line::from("Green".green()),
|
|
||||||
Line::from("Blue".blue()),
|
|
||||||
])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 12));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let mut expected = Buffer::with_lines([
|
|
||||||
"▀██▀▀█▄ ▀██ ",
|
|
||||||
" ██▄▄█▀ ▄█▀▀█▄ ▄▄▄██ ",
|
|
||||||
" ██ ▀█▄ ██▀▀▀▀ ██ ██ ",
|
|
||||||
"▀▀▀ ▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ",
|
|
||||||
" ▄█▀▀█▄ ",
|
|
||||||
"██ ▀█▄█▀█▄ ▄█▀▀█▄ ▄█▀▀█▄ ██▀▀█▄ ",
|
|
||||||
"▀█▄ ▀██ ██ ▀▀ ██▀▀▀▀ ██▀▀▀▀ ██ ██ ",
|
|
||||||
" ▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ",
|
|
||||||
"▀██▀▀█▄ ▀██ ",
|
|
||||||
" ██▄▄█▀ ██ ██ ██ ▄█▀▀█▄ ",
|
|
||||||
" ██ ██ ██ ██ ██ ██▀▀▀▀ ",
|
|
||||||
"▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ▀▀▀▀ ",
|
|
||||||
]);
|
|
||||||
expected.set_style(Rect::new(0, 0, 24, 4), Style::new().red());
|
|
||||||
expected.set_style(Rect::new(0, 4, 40, 4), Style::new().green());
|
|
||||||
expected.set_style(Rect::new(0, 8, 32, 4), Style::new().blue());
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_width_single_line() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfWidth)
|
|
||||||
.lines(vec![Line::from("SingleLine")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▐█▌ █ ▐█ ██ █ ",
|
|
||||||
"█ █ █ ▐▌ ",
|
|
||||||
"█▌ ▐█ ██▌ ▐█▐▌ █ ▐█▌ ▐▌ ▐█ ██▌ ▐█▌ ",
|
|
||||||
"▐█ █ █ █ █ █ █ █ █ ▐▌ █ █ █ █ █ ",
|
|
||||||
" ▐█ █ █ █ █ █ █ ███ ▐▌ ▌ █ █ █ ███ ",
|
|
||||||
"█ █ █ █ █ ▐██ █ █ ▐▌▐▌ █ █ █ █ ",
|
|
||||||
"▐█▌ ▐█▌ █ █ █ ▐█▌ ▐█▌ ███▌▐█▌ █ █ ▐█▌ ",
|
|
||||||
" ██▌ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_width_truncated() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfWidth)
|
|
||||||
.lines(vec![Line::from("Truncated")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 35, 6));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"███ ▐ ▐█",
|
|
||||||
"▌█▐ █ █",
|
|
||||||
" █ █▐█ █ █ ██▌ ▐█▌ ▐█▌ ▐██ ▐█▌ █",
|
|
||||||
" █ ▐█▐▌█ █ █ █ █ █ █ █ █ █ ▐██",
|
|
||||||
" █ ▐▌▐▌█ █ █ █ █ ▐██ █ ███ █ █",
|
|
||||||
" █ ▐▌ █ █ █ █ █ █ █ █ █▐ █ █ █",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_width_multiple_lines() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfWidth)
|
|
||||||
.lines(vec![Line::from("Multi"), Line::from("Lines")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 16));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"█ ▐▌ ▐█ ▐ █ ",
|
|
||||||
"█▌█▌ █ █ ",
|
|
||||||
"███▌█ █ █ ▐██ ▐█ ",
|
|
||||||
"███▌█ █ █ █ █ ",
|
|
||||||
"█▐▐▌█ █ █ █ █ ",
|
|
||||||
"█ ▐▌█ █ █ █▐ █ ",
|
|
||||||
"█ ▐▌▐█▐▌▐█▌ ▐▌ ▐█▌ ",
|
|
||||||
" ",
|
|
||||||
"██ █ ",
|
|
||||||
"▐▌ ",
|
|
||||||
"▐▌ ▐█ ██▌ ▐█▌ ▐██ ",
|
|
||||||
"▐▌ █ █ █ █ █ █ ",
|
|
||||||
"▐▌ ▌ █ █ █ ███ ▐█▌ ",
|
|
||||||
"▐▌▐▌ █ █ █ █ █ ",
|
|
||||||
"███▌▐█▌ █ █ ▐█▌ ██▌ ",
|
|
||||||
" ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_width_widget_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfWidth)
|
|
||||||
.lines(vec![Line::from("Styled")])
|
|
||||||
.style(Style::new().bold())
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 24, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▐█▌ ▐ ▐█ ▐█ ".bold(),
|
|
||||||
"█ █ █ █ █ ".bold(),
|
|
||||||
"█▌ ▐██ █ █ █ ▐█▌ █ ".bold(),
|
|
||||||
"▐█ █ █ █ █ █ █ ▐██ ".bold(),
|
|
||||||
" ▐█ █ █ █ █ ███ █ █ ".bold(),
|
|
||||||
"█ █ █▐ ▐██ █ █ █ █ ".bold(),
|
|
||||||
"▐█▌ ▐▌ █ ▐█▌ ▐█▌ ▐█▐▌".bold(),
|
|
||||||
" ██▌ ".bold(),
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_width_line_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::HalfWidth)
|
|
||||||
.lines(vec![
|
|
||||||
Line::from("Red".red()),
|
|
||||||
Line::from("Green".green()),
|
|
||||||
Line::from("Blue".blue()),
|
|
||||||
])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 24));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let mut expected = Buffer::with_lines([
|
|
||||||
"███ ▐█ ",
|
|
||||||
"▐▌▐▌ █ ",
|
|
||||||
"▐▌▐▌▐█▌ █ ",
|
|
||||||
"▐██ █ █ ▐██ ",
|
|
||||||
"▐▌█ ███ █ █ ",
|
|
||||||
"▐▌▐▌█ █ █ ",
|
|
||||||
"█▌▐▌▐█▌ ▐█▐▌ ",
|
|
||||||
" ",
|
|
||||||
" ██ ",
|
|
||||||
"▐▌▐▌ ",
|
|
||||||
"█ █▐█ ▐█▌ ▐█▌ ██▌ ",
|
|
||||||
"█ ▐█▐▌█ █ █ █ █ █ ",
|
|
||||||
"█ █▌▐▌▐▌███ ███ █ █ ",
|
|
||||||
"▐▌▐▌▐▌ █ █ █ █ ",
|
|
||||||
" ██▌██ ▐█▌ ▐█▌ █ █ ",
|
|
||||||
" ",
|
|
||||||
"███ ▐█ ",
|
|
||||||
"▐▌▐▌ █ ",
|
|
||||||
"▐▌▐▌ █ █ █ ▐█▌ ",
|
|
||||||
"▐██ █ █ █ █ █ ",
|
|
||||||
"▐▌▐▌ █ █ █ ███ ",
|
|
||||||
"▐▌▐▌ █ █ █ █ ",
|
|
||||||
"███ ▐█▌ ▐█▐▌▐█▌ ",
|
|
||||||
" ",
|
|
||||||
]);
|
|
||||||
expected.set_style(Rect::new(0, 0, 12, 8), Style::new().red());
|
|
||||||
expected.set_style(Rect::new(0, 8, 20, 8), Style::new().green());
|
|
||||||
expected.set_style(Rect::new(0, 16, 16, 8), Style::new().blue());
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn check_half_size_symbols() -> Result<()> {
|
|
||||||
assert_eq!(get_symbol_half_size(0, 0, 0, 0), ' ');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 0, 0, 0), '▘');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 1, 0, 0), '▝');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 1, 0, 0), '▀');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 0, 1, 0), '▖');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 0, 1, 0), '▌');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 1, 1, 0), '▞');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 1, 1, 0), '▛');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 0, 0, 1), '▗');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 0, 0, 1), '▚');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 1, 0, 1), '▐');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 1, 0, 1), '▜');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 0, 1, 1), '▄');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 0, 1, 1), '▙');
|
|
||||||
assert_eq!(get_symbol_half_size(0, 1, 1, 1), '▟');
|
|
||||||
assert_eq!(get_symbol_half_size(1, 1, 1, 1), '█');
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_size_single_line() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::Quadrant)
|
|
||||||
.lines(vec![Line::from("SingleLine")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▟▀▙ ▀ ▝█ ▜▛ ▀ ",
|
|
||||||
"▜▙ ▝█ █▀▙ ▟▀▟▘ █ ▟▀▙ ▐▌ ▝█ █▀▙ ▟▀▙ ",
|
|
||||||
"▄▝█ █ █ █ ▜▄█ █ █▀▀ ▐▌▗▌ █ █ █ █▀▀ ",
|
|
||||||
"▝▀▘ ▝▀▘ ▀ ▀ ▄▄▛ ▝▀▘ ▝▀▘ ▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_size_truncated() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::Quadrant)
|
|
||||||
.lines(vec![Line::from("Truncated")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 35, 3));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▛█▜ ▟ ▝█",
|
|
||||||
" █ ▜▟▜▖█ █ █▀▙ ▟▀▙ ▝▀▙ ▝█▀ ▟▀▙ ▗▄█",
|
|
||||||
" █ ▐▌▝▘█ █ █ █ █ ▄ ▟▀█ █▗ █▀▀ █ █",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_size_multiple_lines() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::Quadrant)
|
|
||||||
.lines(vec![Line::from("Multi"), Line::from("Lines")])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 8));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"█▖▟▌ ▝█ ▟ ▀ ",
|
|
||||||
"███▌█ █ █ ▝█▀ ▝█ ",
|
|
||||||
"█▝▐▌█ █ █ █▗ █ ",
|
|
||||||
"▀ ▝▘▝▀▝▘▝▀▘ ▝▘ ▝▀▘ ",
|
|
||||||
"▜▛ ▀ ",
|
|
||||||
"▐▌ ▝█ █▀▙ ▟▀▙ ▟▀▀ ",
|
|
||||||
"▐▌▗▌ █ █ █ █▀▀ ▝▀▙ ",
|
|
||||||
"▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ▀▀▘ ",
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_size_widget_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::Quadrant)
|
|
||||||
.lines(vec![Line::from("Styled")])
|
|
||||||
.style(Style::new().bold())
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 24, 4));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let expected = Buffer::with_lines([
|
|
||||||
"▟▀▙ ▟ ▝█ ▝█ ".bold(),
|
|
||||||
"▜▙ ▝█▀ █ █ █ ▟▀▙ ▗▄█ ".bold(),
|
|
||||||
"▄▝█ █▗ ▜▄█ █ █▀▀ █ █ ".bold(),
|
|
||||||
"▝▀▘ ▝▘ ▄▄▛ ▝▀▘ ▝▀▘ ▝▀▝▘".bold(),
|
|
||||||
]);
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn render_half_size_line_style() -> Result<()> {
|
|
||||||
let big_text = BigTextBuilder::default()
|
|
||||||
.pixel_size(PixelSize::Quadrant)
|
|
||||||
.lines(vec![
|
|
||||||
Line::from("Red".red()),
|
|
||||||
Line::from("Green".green()),
|
|
||||||
Line::from("Blue".blue()),
|
|
||||||
])
|
|
||||||
.build()?;
|
|
||||||
let mut buf = Buffer::empty(Rect::new(0, 0, 20, 12));
|
|
||||||
big_text.render(buf.area, &mut buf);
|
|
||||||
let mut expected = Buffer::with_lines([
|
|
||||||
"▜▛▜▖ ▝█ ",
|
|
||||||
"▐▙▟▘▟▀▙ ▗▄█ ",
|
|
||||||
"▐▌▜▖█▀▀ █ █ ",
|
|
||||||
"▀▘▝▘▝▀▘ ▝▀▝▘ ",
|
|
||||||
"▗▛▜▖ ",
|
|
||||||
"█ ▜▟▜▖▟▀▙ ▟▀▙ █▀▙ ",
|
|
||||||
"▜▖▜▌▐▌▝▘█▀▀ █▀▀ █ █ ",
|
|
||||||
" ▀▀▘▀▀ ▝▀▘ ▝▀▘ ▀ ▀ ",
|
|
||||||
"▜▛▜▖▝█ ",
|
|
||||||
"▐▙▟▘ █ █ █ ▟▀▙ ",
|
|
||||||
"▐▌▐▌ █ █ █ █▀▀ ",
|
|
||||||
"▀▀▀ ▝▀▘ ▝▀▝▘▝▀▘ ",
|
|
||||||
]);
|
|
||||||
expected.set_style(Rect::new(0, 0, 12, 4), Style::new().red());
|
|
||||||
expected.set_style(Rect::new(0, 4, 20, 4), Style::new().green());
|
|
||||||
expected.set_style(Rect::new(0, 8, 16, 4), Style::new().blue());
|
|
||||||
assert_eq!(buf, expected);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -4,19 +4,17 @@ use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Flex, Layout, Rect},
|
layout::{Flex, Layout, Rect},
|
||||||
style::{Color, Style},
|
style::{Color, Style},
|
||||||
|
text::Text,
|
||||||
widgets::Widget,
|
widgets::Widget,
|
||||||
Frame,
|
Frame,
|
||||||
};
|
};
|
||||||
use unicode_width::UnicodeWidthStr;
|
|
||||||
|
|
||||||
use crate::big_text::{BigTextBuilder, PixelSize};
|
|
||||||
|
|
||||||
/// delay the start of the animation so it doesn't start immediately
|
/// delay the start of the animation so it doesn't start immediately
|
||||||
const DELAY: usize = 240;
|
const DELAY: usize = 120;
|
||||||
/// higher means more pixels per frame are modified in the animation
|
/// higher means more pixels per frame are modified in the animation
|
||||||
const DRIP_SPEED: usize = 50;
|
const DRIP_SPEED: usize = 500;
|
||||||
/// delay the start of the text animation so it doesn't start immediately after the initial delay
|
/// delay the start of the text animation so it doesn't start immediately after the initial delay
|
||||||
const TEXT_DELAY: usize = 240;
|
const TEXT_DELAY: usize = 180;
|
||||||
|
|
||||||
/// Destroy mode activated by pressing `d`
|
/// Destroy mode activated by pressing `d`
|
||||||
pub fn destroy(frame: &mut Frame<'_>) {
|
pub fn destroy(frame: &mut Frame<'_>) {
|
||||||
|
@ -86,19 +84,18 @@ fn text(frame_count: usize, area: Rect, buf: &mut Buffer) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let line = "RATATUI";
|
let logo = indoc::indoc! {"
|
||||||
let big_text = BigTextBuilder::default()
|
██████ ████ ██████ ████ ██████ ██ ██ ██
|
||||||
.lines([line.into()])
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
.pixel_size(PixelSize::Full)
|
██████ ████████ ██ ████████ ██ ██ ██ ██
|
||||||
.style(Style::new().fg(Color::Rgb(255, 0, 0)))
|
██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
|
||||||
.build()
|
██ ██ ██ ██ ██ ██ ██ ██ ████ ██
|
||||||
.unwrap();
|
"};
|
||||||
|
let logo_text = Text::styled(logo, Color::Rgb(255, 255, 255));
|
||||||
// the font size is 8x8 for each character and we have 1 line
|
let area = centered_rect(area, logo_text.width() as u16, logo_text.height() as u16);
|
||||||
let area = centered_rect(area, line.width() as u16 * 8, 8);
|
|
||||||
|
|
||||||
let mask_buf = &mut Buffer::empty(area);
|
let mask_buf = &mut Buffer::empty(area);
|
||||||
big_text.render(area, mask_buf);
|
logo_text.render(area, mask_buf);
|
||||||
|
|
||||||
let percentage = (sub_frame as f64 / 480.0).clamp(0.0, 1.0);
|
let percentage = (sub_frame as f64 / 480.0).clamp(0.0, 1.0);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
)]
|
)]
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod big_text;
|
|
||||||
mod colors;
|
mod colors;
|
||||||
mod destroy;
|
mod destroy;
|
||||||
mod errors;
|
mod errors;
|
||||||
|
|
|
@ -10,9 +10,9 @@ Set Width 1120
|
||||||
Set Height 480
|
Set Height 480
|
||||||
Set Padding 0
|
Set Padding 0
|
||||||
Hide
|
Hide
|
||||||
Type "cargo run --example demo2 --features crossterm,widget-calendar"
|
Type "cargo run --example demo2 --features crossterm,palette,widget-calendar"
|
||||||
Enter
|
Enter
|
||||||
Sleep 2s
|
Sleep 2s
|
||||||
Show
|
Show
|
||||||
Type "d"
|
Type "d"
|
||||||
Sleep 30s
|
Sleep 20s
|
||||||
|
|
Loading…
Reference in a new issue