1use alloc::vec::Vec;
2use core::cmp::min;
3
4use derive_builder::Builder;
5use font8x8::UnicodeFonts;
6use ratatui_core::buffer::Buffer;
7use ratatui_core::layout::{Alignment, Rect};
8use ratatui_core::style::Style;
9use ratatui_core::text::{Line, StyledGrapheme};
10use ratatui_core::widgets::Widget;
11use ratatui_widgets::block::{Block, BlockExt};
12
13use crate::PixelSize;
14
15#[derive(Debug, Builder, Clone, PartialEq, Eq, Hash)]
63#[builder(build_fn(skip), no_std)]
64#[non_exhaustive]
65pub struct BigText<'a> {
66 #[builder(default, setter(into))]
68 pub lines: Vec<Line<'a>>,
69
70 #[builder(default, setter(into))]
74 pub style: Style,
75
76 #[builder(default)]
80 pub pixel_size: PixelSize,
81
82 #[builder(default)]
86 pub alignment: Alignment,
87
88 #[builder(default, setter(into, strip_option))]
90 pub block: Option<Block<'a>>,
91}
92
93impl BigText<'static> {
94 pub fn builder() -> BigTextBuilder<'static> {
96 BigTextBuilder::default()
97 }
98}
99
100impl BigTextBuilder<'_> {
101 pub fn left_aligned(&mut self) -> &mut Self {
103 self.alignment(Alignment::Left)
104 }
105
106 pub fn right_aligned(&mut self) -> &mut Self {
108 self.alignment(Alignment::Right)
109 }
110
111 pub fn centered(&mut self) -> &mut Self {
113 self.alignment(Alignment::Center)
114 }
115}
116
117impl<'a> BigTextBuilder<'a> {
118 pub fn build(&self) -> BigText<'a> {
120 BigText {
121 lines: self.lines.as_ref().cloned().unwrap_or_default(),
122 style: self.style.unwrap_or_default(),
123 pixel_size: self.pixel_size.unwrap_or_default(),
124 alignment: self.alignment.unwrap_or_default(),
125 block: self.block.as_ref().cloned().unwrap_or_default(),
126 }
127 }
128}
129
130impl Widget for BigText<'_> {
131 fn render(self, area: Rect, buf: &mut Buffer) {
132 (&self).render(area, buf);
133 }
134}
135
136impl Widget for &BigText<'_> {
137 fn render(self, area: Rect, buf: &mut Buffer) {
138 self.block.as_ref().render(area, buf);
139 let inner = self.block.inner_if_some(area);
140
141 let layout = layout(inner, &self.pixel_size, self.alignment, &self.lines);
142 for (line, line_layout) in self.lines.iter().zip(layout) {
143 for (g, cell) in line.styled_graphemes(self.style).zip(line_layout) {
144 render_symbol(g, cell, buf, &self.pixel_size);
145 }
146 }
147 }
148}
149
150fn layout<'a>(
153 area: Rect,
154 pixel_size: &PixelSize,
155 alignment: Alignment,
156 lines: &'a [Line<'a>],
157) -> impl IntoIterator<Item = impl IntoIterator<Item = Rect> + use<>> + 'a + use<'a> {
158 let (step_x, step_y) = pixel_size.pixels_per_cell();
159 let width = 8_u16.div_ceil(step_x);
160 let height = 8_u16.div_ceil(step_y);
161
162 (area.top()..area.bottom())
163 .step_by(height as usize)
164 .zip(lines.iter())
165 .map(move |(y, line)| {
166 let offset = get_alignment_offset(area.width, width, alignment, line);
167 (area.left() + offset..area.right())
168 .step_by(width as usize)
169 .map(move |x| {
170 let width = min(area.right() - x, width);
171 let height = min(area.bottom() - y, height);
172 Rect::new(x, y, width, height)
173 })
174 })
175}
176
177fn get_alignment_offset<'a>(
178 area_width: u16,
179 letter_width: u16,
180 alignment: Alignment,
181 line: &'a Line<'a>,
182) -> u16 {
183 let line_glyph_count = line.styled_graphemes(Style::default()).count();
185 let big_line_width = line_glyph_count
186 .saturating_mul(usize::from(letter_width))
187 .clamp(0, usize::from(u16::MAX)) as u16;
188 match alignment {
189 Alignment::Center => (area_width / 2).saturating_sub(big_line_width / 2),
190 Alignment::Right => area_width.saturating_sub(big_line_width),
191 Alignment::Left => 0,
192 }
193}
194
195const FONTS: [&dyn UnicodeFonts; 8] = [
196 &font8x8::BASIC_FONTS,
197 &font8x8::LATIN_FONTS,
198 &font8x8::HIRAGANA_FONTS,
199 &font8x8::GREEK_FONTS,
200 &font8x8::BLOCK_FONTS,
201 &font8x8::BOX_FONTS,
202 &font8x8::MISC_FONTS,
203 &font8x8::SGA_FONTS,
204];
205
206fn render_symbol(grapheme: StyledGrapheme, area: Rect, buf: &mut Buffer, pixel_size: &PixelSize) {
209 buf.set_style(area, grapheme.style);
210 let c = grapheme.symbol.chars().next().unwrap(); if let Some(glyph) = FONTS.iter().find_map(|font| font.get(c)) {
212 render_glyph(glyph, area, buf, pixel_size);
213 }
214}
215
216fn render_glyph(glyph: [u8; 8], area: Rect, buf: &mut Buffer, pixel_size: &PixelSize) {
218 let (step_x, step_y) = pixel_size.pixels_per_cell();
219
220 let glyph_vertical_index = (0..glyph.len()).step_by(step_y as usize);
221 let glyph_horizontal_bit_selector = (0..8).step_by(step_x as usize);
222
223 for (y, row) in glyph_vertical_index.zip(area.rows()) {
224 for (x, col) in glyph_horizontal_bit_selector.clone().zip(row.columns()) {
225 buf[col].set_char(pixel_size.symbol_for_position(&glyph, y, x));
226 }
227 }
228}
229
230#[cfg(test)]
231mod tests {
232 use alloc::vec;
233
234 use ratatui_core::style::Stylize;
235
236 use super::*;
237
238 #[test]
239 fn build() {
240 let lines = vec![Line::from(vec!["Hello".red(), "World".blue()])];
241 let style = Style::new().green();
242 let pixel_size = PixelSize::default();
243 let alignment = Alignment::Center;
244 assert_eq!(
245 BigText::builder()
246 .lines(lines.clone())
247 .style(style)
248 .alignment(Alignment::Center)
249 .build(),
250 BigText {
251 lines,
252 style,
253 pixel_size,
254 alignment,
255 block: None,
256 }
257 );
258 }
259
260 #[test]
261 fn render_single_line() {
262 let big_text = BigText::builder()
263 .lines(vec![Line::from("SingleLine")])
264 .build();
265 let mut buf = Buffer::empty(Rect::new(0, 0, 80, 8));
266 big_text.render(buf.area, &mut buf);
267 let expected = Buffer::with_lines(vec![
268 " ████ ██ ███ ████ ██ ",
269 "██ ██ ██ ██ ",
270 "███ ███ █████ ███ ██ ██ ████ ██ ███ █████ ████ ",
271 " ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ",
272 " ███ ██ ██ ██ ██ ██ ██ ██████ ██ █ ██ ██ ██ ██████ ",
273 "██ ██ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ ██ ",
274 " ████ ████ ██ ██ ██ ████ ████ ███████ ████ ██ ██ ████ ",
275 " █████ ",
276 ]);
277 assert_eq!(buf, expected);
278 }
279
280 #[test]
281 fn render_by_reference_matches_owned_render() {
282 let big_text = BigText::builder()
283 .lines(vec![Line::from("Reference")])
284 .build();
285 let mut owned_buf = Buffer::empty(Rect::new(0, 0, 72, 8));
286 let mut borrowed_buf = Buffer::empty(Rect::new(0, 0, 72, 8));
287
288 big_text.clone().render(owned_buf.area, &mut owned_buf);
289 (&big_text).render(borrowed_buf.area, &mut borrowed_buf);
290
291 assert_eq!(borrowed_buf, owned_buf);
292 }
293
294 #[test]
295 fn render_truncated() {
296 let big_text = BigText::builder()
297 .lines(vec![Line::from("Truncated")])
298 .build();
299 let mut buf = Buffer::empty(Rect::new(0, 0, 70, 6));
300 big_text.render(buf.area, &mut buf);
301 let expected = Buffer::with_lines(vec![
302 "██████ █ ███",
303 "█ ██ █ ██ ██",
304 " ██ ██ ███ ██ ██ █████ ████ ████ █████ ████ ██",
305 " ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █████",
306 " ██ ██ ██ ██ ██ ██ ██ ██ █████ ██ ██████ ██ ██",
307 " ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ █ ██ ██ ██",
308 ]);
309 assert_eq!(buf, expected);
310 }
311
312 #[test]
313 fn render_multiple_lines() {
314 let big_text = BigText::builder()
315 .lines(vec![Line::from("Multi"), Line::from("Lines")])
316 .build();
317 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 16));
318 big_text.render(buf.area, &mut buf);
319 let expected = Buffer::with_lines(vec![
320 "██ ██ ███ █ ██ ",
321 "███ ███ ██ ██ ",
322 "███████ ██ ██ ██ █████ ███ ",
323 "███████ ██ ██ ██ ██ ██ ",
324 "██ █ ██ ██ ██ ██ ██ ██ ",
325 "██ ██ ██ ██ ██ ██ █ ██ ",
326 "██ ██ ███ ██ ████ ██ ████ ",
327 " ",
328 "████ ██ ",
329 " ██ ",
330 " ██ ███ █████ ████ █████ ",
331 " ██ ██ ██ ██ ██ ██ ██ ",
332 " ██ █ ██ ██ ██ ██████ ████ ",
333 " ██ ██ ██ ██ ██ ██ ██ ",
334 "███████ ████ ██ ██ ████ █████ ",
335 " ",
336 ]);
337 assert_eq!(buf, expected);
338 }
339
340 #[test]
341 fn render_widget_style() {
342 let big_text = BigText::builder()
343 .lines(vec![Line::from("Styled")])
344 .style(Style::new().bold())
345 .build();
346 let mut buf = Buffer::empty(Rect::new(0, 0, 48, 8));
347 big_text.render(buf.area, &mut buf);
348 let mut expected = Buffer::with_lines(vec![
349 " ████ █ ███ ███ ",
350 "██ ██ ██ ██ ██ ",
351 "███ █████ ██ ██ ██ ████ ██ ",
352 " ███ ██ ██ ██ ██ ██ ██ █████ ",
353 " ███ ██ ██ ██ ██ ██████ ██ ██ ",
354 "██ ██ ██ █ █████ ██ ██ ██ ██ ",
355 " ████ ██ ██ ████ ████ ███ ██ ",
356 " █████ ",
357 ]);
358 expected.set_style(Rect::new(0, 0, 48, 8), Style::new().bold());
359 assert_eq!(buf, expected);
360 }
361
362 #[test]
363 fn render_line_style() {
364 let big_text = BigText::builder()
365 .lines(vec![
366 Line::from("Red".red()),
367 Line::from("Green".green()),
368 Line::from("Blue".blue()),
369 ])
370 .build();
371 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 24));
372 big_text.render(buf.area, &mut buf);
373 let mut expected = Buffer::with_lines(vec![
374 "██████ ███ ",
375 " ██ ██ ██ ",
376 " ██ ██ ████ ██ ",
377 " █████ ██ ██ █████ ",
378 " ██ ██ ██████ ██ ██ ",
379 " ██ ██ ██ ██ ██ ",
380 "███ ██ ████ ███ ██ ",
381 " ",
382 " ████ ",
383 " ██ ██ ",
384 "██ ██ ███ ████ ████ █████ ",
385 "██ ███ ██ ██ ██ ██ ██ ██ ██ ",
386 "██ ███ ██ ██ ██████ ██████ ██ ██ ",
387 " ██ ██ ██ ██ ██ ██ ██ ",
388 " █████ ████ ████ ████ ██ ██ ",
389 " ",
390 "██████ ███ ",
391 " ██ ██ ██ ",
392 " ██ ██ ██ ██ ██ ████ ",
393 " █████ ██ ██ ██ ██ ██ ",
394 " ██ ██ ██ ██ ██ ██████ ",
395 " ██ ██ ██ ██ ██ ██ ",
396 "██████ ████ ███ ██ ████ ",
397 " ",
398 ]);
399 expected.set_style(Rect::new(0, 0, 24, 8), Style::new().red());
400 expected.set_style(Rect::new(0, 8, 40, 8), Style::new().green());
401 expected.set_style(Rect::new(0, 16, 32, 8), Style::new().blue());
402 assert_eq!(buf, expected);
403 }
404
405 #[test]
406 fn render_half_height_single_line() {
407 let big_text = BigText::builder()
408 .pixel_size(PixelSize::HalfHeight)
409 .lines(vec![Line::from("SingleLine")])
410 .build();
411 let mut buf = Buffer::empty(Rect::new(0, 0, 80, 4));
412 big_text.render(buf.area, &mut buf);
413 let expected = Buffer::with_lines(vec![
414 "▄█▀▀█▄ ▀▀ ▀██ ▀██▀ ▀▀ ",
415 "▀██▄ ▀██ ██▀▀█▄ ▄█▀▀▄█▀ ██ ▄█▀▀█▄ ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ",
416 "▄▄ ▀██ ██ ██ ██ ▀█▄▄██ ██ ██▀▀▀▀ ██ ▄█ ██ ██ ██ ██▀▀▀▀ ",
417 " ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ",
418 ]);
419 assert_eq!(buf, expected);
420 }
421
422 #[test]
423 fn render_half_height_truncated() {
424 let big_text = BigText::builder()
425 .pixel_size(PixelSize::HalfHeight)
426 .lines(vec![Line::from("Truncated")])
427 .build();
428 let mut buf = Buffer::empty(Rect::new(0, 0, 70, 3));
429 big_text.render(buf.area, &mut buf);
430 let expected = Buffer::with_lines(vec![
431 "█▀██▀█ ▄█ ▀██",
432 " ██ ▀█▄█▀█▄ ██ ██ ██▀▀█▄ ▄█▀▀█▄ ▀▀▀█▄ ▀██▀▀ ▄█▀▀█▄ ▄▄▄██",
433 " ██ ██ ▀▀ ██ ██ ██ ██ ██ ▄▄ ▄█▀▀██ ██ ▄ ██▀▀▀▀ ██ ██",
434 ]);
435 assert_eq!(buf, expected);
436 }
437
438 #[test]
439 fn render_half_height_multiple_lines() {
440 let big_text = BigText::builder()
441 .pixel_size(PixelSize::HalfHeight)
442 .lines(vec![Line::from("Multi"), Line::from("Lines")])
443 .build();
444 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
445 big_text.render(buf.area, &mut buf);
446 let expected = Buffer::with_lines(vec![
447 "██▄ ▄██ ▀██ ▄█ ▀▀ ",
448 "███████ ██ ██ ██ ▀██▀▀ ▀██ ",
449 "██ ▀ ██ ██ ██ ██ ██ ▄ ██ ",
450 "▀▀ ▀▀ ▀▀▀ ▀▀ ▀▀▀▀ ▀▀ ▀▀▀▀ ",
451 "▀██▀ ▀▀ ",
452 " ██ ▀██ ██▀▀█▄ ▄█▀▀█▄ ▄█▀▀▀▀ ",
453 " ██ ▄█ ██ ██ ██ ██▀▀▀▀ ▀▀▀█▄ ",
454 "▀▀▀▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ▀▀▀▀ ▀▀▀▀▀ ",
455 ]);
456 assert_eq!(buf, expected);
457 }
458
459 #[test]
460 fn render_half_height_widget_style() {
461 let big_text = BigText::builder()
462 .pixel_size(PixelSize::HalfHeight)
463 .lines(vec![Line::from("Styled")])
464 .style(Style::new().bold())
465 .build();
466 let mut buf = Buffer::empty(Rect::new(0, 0, 48, 4));
467 big_text.render(buf.area, &mut buf);
468 let mut expected = Buffer::with_lines(vec![
469 "▄█▀▀█▄ ▄█ ▀██ ▀██ ",
470 "▀██▄ ▀██▀▀ ██ ██ ██ ▄█▀▀█▄ ▄▄▄██ ",
471 "▄▄ ▀██ ██ ▄ ▀█▄▄██ ██ ██▀▀▀▀ ██ ██ ",
472 " ▀▀▀▀ ▀▀ ▄▄▄▄█▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ",
473 ]);
474 expected.set_style(Rect::new(0, 0, 48, 4), Style::new().bold());
475 assert_eq!(buf, expected);
476 }
477
478 #[test]
479 fn render_half_height_line_style() {
480 let big_text = BigText::builder()
481 .pixel_size(PixelSize::HalfHeight)
482 .lines(vec![
483 Line::from("Red".red()),
484 Line::from("Green".green()),
485 Line::from("Blue".blue()),
486 ])
487 .build();
488 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 12));
489 big_text.render(buf.area, &mut buf);
490 let mut expected = Buffer::with_lines(vec![
491 "▀██▀▀█▄ ▀██ ",
492 " ██▄▄█▀ ▄█▀▀█▄ ▄▄▄██ ",
493 " ██ ▀█▄ ██▀▀▀▀ ██ ██ ",
494 "▀▀▀ ▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ",
495 " ▄█▀▀█▄ ",
496 "██ ▀█▄█▀█▄ ▄█▀▀█▄ ▄█▀▀█▄ ██▀▀█▄ ",
497 "▀█▄ ▀██ ██ ▀▀ ██▀▀▀▀ ██▀▀▀▀ ██ ██ ",
498 " ▀▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀ ▀▀ ",
499 "▀██▀▀█▄ ▀██ ",
500 " ██▄▄█▀ ██ ██ ██ ▄█▀▀█▄ ",
501 " ██ ██ ██ ██ ██ ██▀▀▀▀ ",
502 "▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀ ▀▀ ▀▀▀▀ ",
503 ]);
504 expected.set_style(Rect::new(0, 0, 24, 4), Style::new().red());
505 expected.set_style(Rect::new(0, 4, 40, 4), Style::new().green());
506 expected.set_style(Rect::new(0, 8, 32, 4), Style::new().blue());
507 assert_eq!(buf, expected);
508 }
509
510 #[test]
511 fn render_half_width_single_line() {
512 let big_text = BigText::builder()
513 .pixel_size(PixelSize::HalfWidth)
514 .lines(vec![Line::from("SingleLine")])
515 .build();
516 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
517 big_text.render(buf.area, &mut buf);
518 let expected = Buffer::with_lines(vec![
519 "▐█▌ █ ▐█ ██ █ ",
520 "█ █ █ ▐▌ ",
521 "█▌ ▐█ ██▌ ▐█▐▌ █ ▐█▌ ▐▌ ▐█ ██▌ ▐█▌ ",
522 "▐█ █ █ █ █ █ █ █ █ ▐▌ █ █ █ █ █ ",
523 " ▐█ █ █ █ █ █ █ ███ ▐▌ ▌ █ █ █ ███ ",
524 "█ █ █ █ █ ▐██ █ █ ▐▌▐▌ █ █ █ █ ",
525 "▐█▌ ▐█▌ █ █ █ ▐█▌ ▐█▌ ███▌▐█▌ █ █ ▐█▌ ",
526 " ██▌ ",
527 ]);
528 assert_eq!(buf, expected);
529 }
530
531 #[test]
532 fn render_half_width_truncated() {
533 let big_text = BigText::builder()
534 .pixel_size(PixelSize::HalfWidth)
535 .lines(vec![Line::from("Truncated")])
536 .build();
537 let mut buf = Buffer::empty(Rect::new(0, 0, 35, 6));
538 big_text.render(buf.area, &mut buf);
539 let expected = Buffer::with_lines(vec![
540 "███ ▐ ▐█",
541 "▌█▐ █ █",
542 " █ █▐█ █ █ ██▌ ▐█▌ ▐█▌ ▐██ ▐█▌ █",
543 " █ ▐█▐▌█ █ █ █ █ █ █ █ █ █ ▐██",
544 " █ ▐▌▐▌█ █ █ █ █ ▐██ █ ███ █ █",
545 " █ ▐▌ █ █ █ █ █ █ █ █ █▐ █ █ █",
546 ]);
547 assert_eq!(buf, expected);
548 }
549
550 #[test]
551 fn render_half_width_multiple_lines() {
552 let big_text = BigText::builder()
553 .pixel_size(PixelSize::HalfWidth)
554 .lines(vec![Line::from("Multi"), Line::from("Lines")])
555 .build();
556 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 16));
557 big_text.render(buf.area, &mut buf);
558 let expected = Buffer::with_lines(vec![
559 "█ ▐▌ ▐█ ▐ █ ",
560 "█▌█▌ █ █ ",
561 "███▌█ █ █ ▐██ ▐█ ",
562 "███▌█ █ █ █ █ ",
563 "█▐▐▌█ █ █ █ █ ",
564 "█ ▐▌█ █ █ █▐ █ ",
565 "█ ▐▌▐█▐▌▐█▌ ▐▌ ▐█▌ ",
566 " ",
567 "██ █ ",
568 "▐▌ ",
569 "▐▌ ▐█ ██▌ ▐█▌ ▐██ ",
570 "▐▌ █ █ █ █ █ █ ",
571 "▐▌ ▌ █ █ █ ███ ▐█▌ ",
572 "▐▌▐▌ █ █ █ █ █ ",
573 "███▌▐█▌ █ █ ▐█▌ ██▌ ",
574 " ",
575 ]);
576 assert_eq!(buf, expected);
577 }
578
579 #[test]
580 fn render_half_width_widget_style() {
581 let big_text = BigText::builder()
582 .pixel_size(PixelSize::HalfWidth)
583 .lines(vec![Line::from("Styled")])
584 .style(Style::new().bold())
585 .build();
586 let mut buf = Buffer::empty(Rect::new(0, 0, 24, 8));
587 big_text.render(buf.area, &mut buf);
588 let mut expected = Buffer::with_lines(vec![
589 "▐█▌ ▐ ▐█ ▐█ ",
590 "█ █ █ █ █ ",
591 "█▌ ▐██ █ █ █ ▐█▌ █ ",
592 "▐█ █ █ █ █ █ █ ▐██ ",
593 " ▐█ █ █ █ █ ███ █ █ ",
594 "█ █ █▐ ▐██ █ █ █ █ ",
595 "▐█▌ ▐▌ █ ▐█▌ ▐█▌ ▐█▐▌",
596 " ██▌ ",
597 ]);
598 expected.set_style(Rect::new(0, 0, 24, 8), Style::new().bold());
599 assert_eq!(buf, expected);
600 }
601
602 #[test]
603 fn render_half_width_line_style() {
604 let big_text = BigText::builder()
605 .pixel_size(PixelSize::HalfWidth)
606 .lines(vec![
607 Line::from("Red".red()),
608 Line::from("Green".green()),
609 Line::from("Blue".blue()),
610 ])
611 .build();
612 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 24));
613 big_text.render(buf.area, &mut buf);
614 let mut expected = Buffer::with_lines(vec![
615 "███ ▐█ ",
616 "▐▌▐▌ █ ",
617 "▐▌▐▌▐█▌ █ ",
618 "▐██ █ █ ▐██ ",
619 "▐▌█ ███ █ █ ",
620 "▐▌▐▌█ █ █ ",
621 "█▌▐▌▐█▌ ▐█▐▌ ",
622 " ",
623 " ██ ",
624 "▐▌▐▌ ",
625 "█ █▐█ ▐█▌ ▐█▌ ██▌ ",
626 "█ ▐█▐▌█ █ █ █ █ █ ",
627 "█ █▌▐▌▐▌███ ███ █ █ ",
628 "▐▌▐▌▐▌ █ █ █ █ ",
629 " ██▌██ ▐█▌ ▐█▌ █ █ ",
630 " ",
631 "███ ▐█ ",
632 "▐▌▐▌ █ ",
633 "▐▌▐▌ █ █ █ ▐█▌ ",
634 "▐██ █ █ █ █ █ ",
635 "▐▌▐▌ █ █ █ ███ ",
636 "▐▌▐▌ █ █ █ █ ",
637 "███ ▐█▌ ▐█▐▌▐█▌ ",
638 " ",
639 ]);
640 expected.set_style(Rect::new(0, 0, 12, 8), Style::new().red());
641 expected.set_style(Rect::new(0, 8, 20, 8), Style::new().green());
642 expected.set_style(Rect::new(0, 16, 16, 8), Style::new().blue());
643 assert_eq!(buf, expected);
644 }
645
646 #[test]
647 fn render_quadrant_size_single_line() {
648 let big_text = BigText::builder()
649 .pixel_size(PixelSize::Quadrant)
650 .lines(vec![Line::from("SingleLine")])
651 .build();
652 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
653 big_text.render(buf.area, &mut buf);
654 let expected = Buffer::with_lines(vec![
655 "▟▀▙ ▀ ▝█ ▜▛ ▀ ",
656 "▜▙ ▝█ █▀▙ ▟▀▟▘ █ ▟▀▙ ▐▌ ▝█ █▀▙ ▟▀▙ ",
657 "▄▝█ █ █ █ ▜▄█ █ █▀▀ ▐▌▗▌ █ █ █ █▀▀ ",
658 "▝▀▘ ▝▀▘ ▀ ▀ ▄▄▛ ▝▀▘ ▝▀▘ ▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ",
659 ]);
660 assert_eq!(buf, expected);
661 }
662
663 #[test]
664 fn render_quadrant_size_truncated() {
665 let big_text = BigText::builder()
666 .pixel_size(PixelSize::Quadrant)
667 .lines(vec![Line::from("Truncated")])
668 .build();
669 let mut buf = Buffer::empty(Rect::new(0, 0, 35, 3));
670 big_text.render(buf.area, &mut buf);
671 let expected = Buffer::with_lines(vec![
672 "▛█▜ ▟ ▝█",
673 " █ ▜▟▜▖█ █ █▀▙ ▟▀▙ ▝▀▙ ▝█▀ ▟▀▙ ▗▄█",
674 " █ ▐▌▝▘█ █ █ █ █ ▄ ▟▀█ █▗ █▀▀ █ █",
675 ]);
676 assert_eq!(buf, expected);
677 }
678
679 #[test]
680 fn render_quadrant_size_multiple_lines() {
681 let big_text = BigText::builder()
682 .pixel_size(PixelSize::Quadrant)
683 .lines(vec![Line::from("Multi"), Line::from("Lines")])
684 .build();
685 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 8));
686 big_text.render(buf.area, &mut buf);
687 let expected = Buffer::with_lines(vec![
688 "█▖▟▌ ▝█ ▟ ▀ ",
689 "███▌█ █ █ ▝█▀ ▝█ ",
690 "█▝▐▌█ █ █ █▗ █ ",
691 "▀ ▝▘▝▀▝▘▝▀▘ ▝▘ ▝▀▘ ",
692 "▜▛ ▀ ",
693 "▐▌ ▝█ █▀▙ ▟▀▙ ▟▀▀ ",
694 "▐▌▗▌ █ █ █ █▀▀ ▝▀▙ ",
695 "▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ▀▀▘ ",
696 ]);
697 assert_eq!(buf, expected);
698 }
699
700 #[test]
701 fn render_quadrant_size_widget_style() {
702 let big_text = BigText::builder()
703 .pixel_size(PixelSize::Quadrant)
704 .lines(vec![Line::from("Styled")])
705 .style(Style::new().bold())
706 .build();
707 let mut buf = Buffer::empty(Rect::new(0, 0, 24, 4));
708 big_text.render(buf.area, &mut buf);
709 let mut expected = Buffer::with_lines(vec![
710 "▟▀▙ ▟ ▝█ ▝█ ",
711 "▜▙ ▝█▀ █ █ █ ▟▀▙ ▗▄█ ",
712 "▄▝█ █▗ ▜▄█ █ █▀▀ █ █ ",
713 "▝▀▘ ▝▘ ▄▄▛ ▝▀▘ ▝▀▘ ▝▀▝▘",
714 ]);
715 expected.set_style(Rect::new(0, 0, 24, 4), Style::new().bold());
716 assert_eq!(buf, expected);
717 }
718
719 #[test]
720 fn render_quadrant_size_line_style() {
721 let big_text = BigText::builder()
722 .pixel_size(PixelSize::Quadrant)
723 .lines(vec![
724 Line::from("Red".red()),
725 Line::from("Green".green()),
726 Line::from("Blue".blue()),
727 ])
728 .build();
729 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 12));
730 big_text.render(buf.area, &mut buf);
731 let mut expected = Buffer::with_lines(vec![
732 "▜▛▜▖ ▝█ ",
733 "▐▙▟▘▟▀▙ ▗▄█ ",
734 "▐▌▜▖█▀▀ █ █ ",
735 "▀▘▝▘▝▀▘ ▝▀▝▘ ",
736 "▗▛▜▖ ",
737 "█ ▜▟▜▖▟▀▙ ▟▀▙ █▀▙ ",
738 "▜▖▜▌▐▌▝▘█▀▀ █▀▀ █ █ ",
739 " ▀▀▘▀▀ ▝▀▘ ▝▀▘ ▀ ▀ ",
740 "▜▛▜▖▝█ ",
741 "▐▙▟▘ █ █ █ ▟▀▙ ",
742 "▐▌▐▌ █ █ █ █▀▀ ",
743 "▀▀▀ ▝▀▘ ▝▀▝▘▝▀▘ ",
744 ]);
745 expected.set_style(Rect::new(0, 0, 12, 4), Style::new().red());
746 expected.set_style(Rect::new(0, 4, 20, 4), Style::new().green());
747 expected.set_style(Rect::new(0, 8, 16, 4), Style::new().blue());
748 assert_eq!(buf, expected);
749 }
750
751 #[test]
752 fn render_third_height_single_line() {
753 let big_text = BigText::builder()
754 .pixel_size(PixelSize::ThirdHeight)
755 .lines(vec![Line::from("SingleLine")])
756 .build();
757 let mut buf = Buffer::empty(Rect::new(0, 0, 80, 3));
758 big_text.render(buf.area, &mut buf);
759 let expected = Buffer::with_lines(vec![
760 "🬹█🬰🬂🬎🬋 🬭🬰🬰 🬭🬭🬭🬭🬭 🬭🬭🬭 🬭🬭 🬂██ 🬭🬭🬭🬭 🬂██🬂 🬭🬰🬰 🬭🬭🬭🬭🬭 🬭🬭🬭🬭 ",
761 "🬭🬰🬂🬎🬹🬹 ██ ██ ██ 🬎█🬭🬭██ ██ ██🬋🬋🬎🬎 ██ 🬭🬹 ██ ██ ██ ██🬋🬋🬎🬎 ",
762 " 🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂 🬂🬂 🬋🬋🬋🬋🬎🬂 🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂🬂🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂 🬂🬂 🬂🬂🬂🬂 ",
763 ]);
764 assert_eq!(buf, expected);
765 }
766
767 #[test]
768 fn render_third_height_truncated() {
769 let big_text = BigText::builder()
770 .pixel_size(PixelSize::ThirdHeight)
771 .lines(vec![Line::from("Truncated")])
772 .build();
773 let mut buf = Buffer::empty(Rect::new(0, 0, 70, 2));
774 big_text.render(buf.area, &mut buf);
775 let expected = Buffer::with_lines(vec![
776 "🬎🬂██🬂🬎 🬭🬭 🬭🬭🬭 🬭🬭 🬭🬭 🬭🬭🬭🬭🬭 🬭🬭🬭🬭 🬭🬭🬭🬭 🬭🬹█🬭🬭 🬭🬭🬭🬭 🬂██",
777 " ██ ██🬂 🬎🬎 ██ ██ ██ ██ ██ 🬰🬰 🬭🬹🬋🬋██ ██ 🬭 ██🬋🬋🬎🬎 🬹█🬂🬂██",
778 ]);
779 assert_eq!(buf, expected);
780 }
781
782 #[test]
783 fn render_third_height_multiple_lines() {
784 let big_text = BigText::builder()
785 .pixel_size(PixelSize::ThirdHeight)
786 .lines(vec![Line::from("Multi"), Line::from("Lines")])
787 .build();
788 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 6));
789 big_text.render(buf.area, &mut buf);
790 let expected = Buffer::with_lines(vec![
791 "██🬹🬭🬹██ 🬭🬭 🬭🬭 🬂██ 🬭🬹█🬭🬭 🬭🬰🬰 ",
792 "██🬂🬎🬂██ ██ ██ ██ ██ 🬭 ██ ",
793 "🬂🬂 🬂🬂 🬂🬂🬂 🬂🬂 🬂🬂🬂🬂 🬂🬂 🬂🬂🬂🬂 ",
794 "🬂██🬂 🬭🬰🬰 🬭🬭🬭🬭🬭 🬭🬭🬭🬭 🬭🬭🬭🬭🬭 ",
795 " ██ 🬭🬹 ██ ██ ██ ██🬋🬋🬎🬎 🬂🬎🬋🬋🬹🬭 ",
796 "🬂🬂🬂🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂 🬂🬂 🬂🬂🬂🬂 🬂🬂🬂🬂🬂 ",
797 ]);
798 assert_eq!(buf, expected);
799 }
800
801 #[test]
802 fn render_third_height_widget_style() {
803 let big_text = BigText::builder()
804 .pixel_size(PixelSize::ThirdHeight)
805 .lines(vec![Line::from("Styled")])
806 .style(Style::new().bold())
807 .build();
808 let mut buf = Buffer::empty(Rect::new(0, 0, 48, 3));
809 big_text.render(buf.area, &mut buf);
810 let mut expected = Buffer::with_lines(vec![
811 "🬹█🬰🬂🬎🬋 🬭🬹█🬭🬭 🬭🬭 🬭🬭 🬂██ 🬭🬭🬭🬭 🬂██ ",
812 "🬭🬰🬂🬎🬹🬹 ██ 🬭 🬎█🬭🬭██ ██ ██🬋🬋🬎🬎 🬹█🬂🬂██ ",
813 " 🬂🬂🬂🬂 🬂🬂 🬋🬋🬋🬋🬎🬂 🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂🬂 🬂🬂 ",
814 ]);
815 expected.set_style(Rect::new(0, 0, 48, 3), Style::new().bold());
816 assert_eq!(buf, expected);
817 }
818
819 #[test]
820 fn render_third_height_line_style() {
821 let big_text = BigText::builder()
822 .pixel_size(PixelSize::ThirdHeight)
823 .lines(vec![
824 Line::from("Red".red()),
825 Line::from("Green".green()),
826 Line::from("Blue".blue()),
827 ])
828 .build();
829 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 9));
830 big_text.render(buf.area, &mut buf);
831 let mut expected = Buffer::with_lines(vec![
832 "🬂██🬂🬂█🬹 🬭🬭🬭🬭 🬂██ ",
833 " ██🬂🬎█🬭 ██🬋🬋🬎🬎 🬹█🬂🬂██ ",
834 "🬂🬂🬂 🬂🬂 🬂🬂🬂🬂 🬂🬂🬂 🬂🬂 ",
835 "🬭🬹🬎🬂🬂🬎🬋 🬭🬭 🬭🬭🬭 🬭🬭🬭🬭 🬭🬭🬭🬭 🬭🬭🬭🬭🬭 ",
836 "🬎█🬭 🬋🬹🬹 ██🬂 🬎🬎 ██🬋🬋🬎🬎 ██🬋🬋🬎🬎 ██ ██ ",
837 " 🬂🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂 🬂🬂 ",
838 "🬂██🬂🬂█🬹 🬂██ 🬭🬭 🬭🬭 🬭🬭🬭🬭 ",
839 " ██🬂🬂█🬹 ██ ██ ██ ██🬋🬋🬎🬎 ",
840 "🬂🬂🬂🬂🬂🬂 🬂🬂🬂🬂 🬂🬂🬂 🬂🬂 🬂🬂🬂🬂 ",
841 ]);
842 expected.set_style(Rect::new(0, 0, 24, 3), Style::new().red());
843 expected.set_style(Rect::new(0, 3, 40, 3), Style::new().green());
844 expected.set_style(Rect::new(0, 6, 32, 3), Style::new().blue());
845 assert_eq!(buf, expected);
846 }
847
848 #[test]
849 fn render_sextant_size_single_line() {
850 let big_text = BigText::builder()
851 .pixel_size(PixelSize::Sextant)
852 .lines(vec![Line::from("SingleLine")])
853 .build();
854 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 3));
855 big_text.render(buf.area, &mut buf);
856 let expected = Buffer::with_lines(vec![
857 "🬻🬒🬌 🬞🬰 🬭🬭🬏 🬞🬭🬞🬏🬁█ 🬞🬭🬏 🬨🬕 🬞🬰 🬭🬭🬏 🬞🬭🬏 ",
858 "🬯🬊🬹 █ █ █ 🬬🬭█ █ █🬋🬎 ▐▌🬞🬓 █ █ █ █🬋🬎 ",
859 "🬁🬂🬀 🬁🬂🬀 🬂 🬂 🬋🬋🬆 🬁🬂🬀 🬁🬂🬀 🬂🬂🬂🬀🬁🬂🬀 🬂 🬂 🬁🬂🬀 ",
860 ]);
861 assert_eq!(buf, expected);
862 }
863
864 #[test]
865 fn render_sextant_size_truncated() {
866 let big_text = BigText::builder()
867 .pixel_size(PixelSize::Sextant)
868 .lines(vec![Line::from("Truncated")])
869 .build();
870 let mut buf = Buffer::empty(Rect::new(0, 0, 35, 2));
871 big_text.render(buf.area, &mut buf);
872 let expected = Buffer::with_lines(vec![
873 "🬆█🬊 🬭🬞🬭 🬭 🬭 🬭🬭🬏 🬞🬭🬏 🬞🬭🬏 🬞🬻🬭 🬞🬭🬏 🬁█",
874 " █ ▐🬕🬉🬄█ █ █ █ █ 🬰 🬵🬋█ █🬞 █🬋🬎 🬻🬂█",
875 ]);
876 assert_eq!(buf, expected);
877 }
878
879 #[test]
880 fn render_sextant_size_multiple_lines() {
881 let big_text = BigText::builder()
882 .pixel_size(PixelSize::Sextant)
883 .lines(vec![Line::from("Multi"), Line::from("Lines")])
884 .build();
885 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 6));
886 big_text.render(buf.area, &mut buf);
887 let expected = Buffer::with_lines(vec![
888 "█🬱🬻▌🬭 🬭 🬁█ 🬞🬻🬭 🬞🬰 ",
889 "█🬊🬨▌█ █ █ █🬞 █ ",
890 "🬂 🬁🬀🬁🬂🬁🬀🬁🬂🬀 🬁🬀 🬁🬂🬀 ",
891 "🬨🬕 🬞🬰 🬭🬭🬏 🬞🬭🬏 🬞🬭🬭 ",
892 "▐▌🬞🬓 █ █ █ █🬋🬎 🬊🬋🬱 ",
893 "🬂🬂🬂🬀🬁🬂🬀 🬂 🬂 🬁🬂🬀 🬂🬂🬀 ",
894 ]);
895 assert_eq!(buf, expected);
896 }
897
898 #[test]
899 fn render_sextant_size_widget_style() {
900 let big_text = BigText::builder()
901 .pixel_size(PixelSize::Sextant)
902 .lines(vec![Line::from("Styled")])
903 .style(Style::new().bold())
904 .build();
905 let mut buf = Buffer::empty(Rect::new(0, 0, 24, 3));
906 big_text.render(buf.area, &mut buf);
907 let mut expected = Buffer::with_lines(vec![
908 "🬻🬒🬌 🬞🬻🬭 🬭 🬭 🬁█ 🬞🬭🬏 🬁█ ",
909 "🬯🬊🬹 █🬞 🬬🬭█ █ █🬋🬎 🬻🬂█ ",
910 "🬁🬂🬀 🬁🬀 🬋🬋🬆 🬁🬂🬀 🬁🬂🬀 🬁🬂🬁🬀",
911 ]);
912 expected.set_style(Rect::new(0, 0, 24, 3), Style::new().bold());
913 assert_eq!(buf, expected);
914 }
915
916 #[test]
917 fn render_sextant_size_line_style() {
918 let big_text = BigText::builder()
919 .pixel_size(PixelSize::Sextant)
920 .lines(vec![
921 Line::from("Red".red()),
922 Line::from("Green".green()),
923 Line::from("Blue".blue()),
924 ])
925 .build();
926 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 9));
927 big_text.render(buf.area, &mut buf);
928 let mut expected = Buffer::with_lines(vec![
929 "🬨🬕🬨🬓🬞🬭🬏 🬁█ ",
930 "▐🬕🬬🬏█🬋🬎 🬻🬂█ ",
931 "🬂🬀🬁🬀🬁🬂🬀 🬁🬂🬁🬀 ",
932 "🬵🬆🬊🬃🬭🬞🬭 🬞🬭🬏 🬞🬭🬏 🬭🬭🬏 ",
933 "🬬🬏🬩🬓▐🬕🬉🬄█🬋🬎 █🬋🬎 █ █ ",
934 " 🬂🬂🬀🬂🬂 🬁🬂🬀 🬁🬂🬀 🬂 🬂 ",
935 "🬨🬕🬨🬓🬁█ 🬭 🬭 🬞🬭🬏 ",
936 "▐🬕🬨🬓 █ █ █ █🬋🬎 ",
937 "🬂🬂🬂 🬁🬂🬀 🬁🬂🬁🬀🬁🬂🬀 ",
938 ]);
939 expected.set_style(Rect::new(0, 0, 12, 3), Style::new().red());
940 expected.set_style(Rect::new(0, 3, 20, 3), Style::new().green());
941 expected.set_style(Rect::new(0, 6, 16, 3), Style::new().blue());
942 assert_eq!(buf, expected);
943 }
944
945 #[test]
946 fn render_quarter_height_single_line() {
947 let big_text = BigText::builder()
948 .pixel_size(PixelSize::QuarterHeight)
949 .lines(vec![Line::from("SingleLine")])
950 .build();
951 let mut buf = Buffer::empty(Rect::new(0, 0, 80, 2));
952 big_text.render(buf.area, &mut buf);
953 let expected = Buffer::with_lines(vec![
954 "█▀ ▄▄▄▂ ▂▄▂▄ 🮂██ ▂▄▄▂ 🮂██🮂 ▄▄▄▂ ▂▄▄▂ ",
955 "🮅▀ 🮅🮅 🮅🮅 🮅🮅 █🮅 🮅🮅 ▀🮅🮂 🮅🮅🮅 🮅🮅 🮅🮅 🮅🮅 ▀🮅🮂 ",
956 ]);
957 assert_eq!(buf, expected);
958 }
959
960 #[test]
961 fn render_quarter_height_truncated() {
962 let big_text = BigText::builder()
963 .pixel_size(PixelSize::QuarterHeight)
964 .lines(vec![Line::from("Truncated")])
965 .build();
966 let mut buf = Buffer::empty(Rect::new(0, 0, 70, 1));
967 big_text.render(buf.area, &mut buf);
968 let expected = Buffer::with_lines(vec![
969 "▀🮂██🮂▀ ▄▂▄▄▂ ▄▄ ▄▄ ▄▄▄▂ ▂▄▄▂ ▄▂ ▆█ ▂▄▄▂ ▂▂██",
970 ]);
971 assert_eq!(buf, expected);
972 }
973
974 #[test]
975 fn render_quarter_height_multiple_lines() {
976 let big_text = BigText::builder()
977 .pixel_size(PixelSize::QuarterHeight)
978 .lines(vec![Line::from("Multi"), Line::from("Lines")])
979 .build();
980 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
981 big_text.render(buf.area, &mut buf);
982 let expected = Buffer::with_lines(vec![
983 "██▆▄▆██ ▄▄ ▄▄ 🮂██ ▆█ ",
984 "🮅🮅 🮂 🮅🮅 ▀🮅▀🮅 🮅🮅 ▀🮅 🮅🮅 ",
985 "🮂██🮂 ▄▄▄▂ ▂▄▄▂ ▂▄ ",
986 "🮅🮅🮅 🮅🮅 🮅🮅 🮅🮅 ▀🮅🮂 🮅 ",
987 ]);
988 assert_eq!(buf, expected);
989 }
990
991 #[test]
992 fn render_quarter_height_widget_style() {
993 let big_text = BigText::builder()
994 .pixel_size(PixelSize::QuarterHeight)
995 .lines(vec![Line::from("Styled")])
996 .style(Style::new().bold())
997 .build();
998 let mut buf = Buffer::empty(Rect::new(0, 0, 48, 2));
999 big_text.render(buf.area, &mut buf);
1000 let mut expected = Buffer::with_lines(vec![
1001 "█▀ ▆█ ▄▄ ▄▄ 🮂██ ▂▄▄▂ ▂▂██ ",
1002 "🮅▀ ▀🮅 █🮅 🮅🮅 ▀🮅🮂 ▀🮅▀🮅 ",
1003 ]);
1004 expected.set_style(Rect::new(0, 0, 48, 2), Style::new().bold());
1005 assert_eq!(buf, expected);
1006 }
1007
1008 #[test]
1009 fn render_quarter_height_line_style() {
1010 let big_text = BigText::builder()
1011 .pixel_size(PixelSize::QuarterHeight)
1012 .lines(vec![
1013 Line::from("Red".red()),
1014 Line::from("Green".green()),
1015 Line::from("Blue".blue()),
1016 ])
1017 .build();
1018 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 6));
1019 big_text.render(buf.area, &mut buf);
1020 let mut expected = Buffer::with_lines(vec![
1021 "🮂███ ▂▄▄▂ ▂▂██ ",
1022 "🮅🮅 🮂🮅 ▀🮅🮂 ▀🮅▀🮅 ",
1023 "▄▆▀🮂🮂▀ ▄▂▄▄▂ ▂▄▄▂ ▂▄▄▂ ▄▄▄▂ ",
1024 "🮂▀🮅🮅 🮅🮅 🮂🮂 ▀🮅🮂 ▀🮅🮂 🮅🮅 🮅🮅 ",
1025 "🮂███ 🮂██ ▄▄ ▄▄ ▂▄▄▂ ",
1026 "🮅🮅🮅▀ 🮅🮅 ▀🮅▀🮅 ▀🮅🮂 ",
1027 ]);
1028 expected.set_style(Rect::new(0, 0, 24, 2), Style::new().red());
1029 expected.set_style(Rect::new(0, 2, 40, 2), Style::new().green());
1030 expected.set_style(Rect::new(0, 4, 32, 2), Style::new().blue());
1031 assert_eq!(buf, expected);
1032 }
1033
1034 #[test]
1035 fn render_octant_size_single_line() {
1036 let big_text = BigText::builder()
1037 .pixel_size(PixelSize::Octant)
1038 .lines(vec![Line::from("SingleLine")])
1039 .build();
1040 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 2));
1041 big_text.render(buf.area, &mut buf);
1042 let expected = Buffer::with_lines(vec![
1043 " ▄ █ ▄ ",
1044 " 🮅 🮅 🮅 🮅 🮅 🮅 🮅 ",
1045 ]);
1046 assert_eq!(buf, expected);
1047 }
1048
1049 #[test]
1050 #[rustfmt::skip]
1051 fn render_octant_size_truncated() {
1052 let big_text = BigText::builder()
1053 .pixel_size(PixelSize::Octant)
1054 .lines(vec![Line::from("Truncated")])
1055 .build();
1056 let mut buf = Buffer::empty(Rect::new(0, 0, 35, 1));
1057 big_text.render(buf.area, &mut buf);
1058 let expected = Buffer::with_lines(vec![
1059 "█ ▄ ▄ ▄ █",
1060 ]);
1061 assert_eq!(buf, expected);
1062 }
1063
1064 #[test]
1065 fn render_octant_size_multiple_lines() {
1066 let big_text = BigText::builder()
1067 .pixel_size(PixelSize::Octant)
1068 .lines(vec![Line::from("Multi"), Line::from("Lines")])
1069 .build();
1070 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 4));
1071 big_text.render(buf.area, &mut buf);
1072 let expected = Buffer::with_lines(vec![
1073 "█▌▄ ▄ █ ",
1074 "🮅🮅 🮅 ",
1075 " ▄ ",
1076 "🮅 🮅 🮅 ",
1077 ]);
1078 assert_eq!(buf, expected);
1079 }
1080
1081 #[test]
1082 #[rustfmt::skip]
1083 fn render_octant_size_widget_style() {
1084 let big_text = BigText::builder()
1085 .pixel_size(PixelSize::Octant)
1086 .lines(vec![Line::from("Styled")])
1087 .style(Style::new().bold())
1088 .build();
1089 let mut buf = Buffer::empty(Rect::new(0, 0, 24, 2));
1090 big_text.render(buf.area, &mut buf);
1091 let mut expected = Buffer::with_lines(vec![
1092 " ▄ ▄ █ █ ",
1093 " 🮅 ",
1094 ]);
1095 expected.set_style(Rect::new(0, 0, 24, 2), Style::new().bold());
1096 assert_eq!(buf, expected);
1097 }
1098
1099 #[test]
1100 fn render_octant_size_line_style() {
1101 let big_text = BigText::builder()
1102 .pixel_size(PixelSize::Octant)
1103 .lines(vec![
1104 Line::from("Red".red()),
1105 Line::from("Green".green()),
1106 Line::from("Blue".blue()),
1107 ])
1108 .build();
1109 let mut buf = Buffer::empty(Rect::new(0, 0, 20, 6));
1110 big_text.render(buf.area, &mut buf);
1111 let mut expected = Buffer::with_lines(vec![
1112 " █ ",
1113 " ",
1114 " ▄ ",
1115 " 🮅 🮅 ",
1116 "█ ▄ ▄ ",
1117 "▘🮅 ",
1118 ]);
1119 expected.set_style(Rect::new(0, 0, 12, 2), Style::new().red());
1120 expected.set_style(Rect::new(0, 2, 20, 2), Style::new().green());
1121 expected.set_style(Rect::new(0, 4, 16, 2), Style::new().blue());
1122 assert_eq!(buf, expected);
1123 }
1124
1125 #[test]
1126 fn render_alignment_left() {
1127 let big_text = BigText::builder()
1128 .pixel_size(PixelSize::Quadrant)
1129 .lines(vec![Line::from("Left")])
1130 .alignment(Alignment::Left)
1131 .build();
1132 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
1133 big_text.render(buf.area, &mut buf);
1134 let expected = Buffer::with_lines(vec![
1135 "▜▛ ▗▛▙ ▟ ",
1136 "▐▌ ▟▀▙ ▟▙ ▝█▀ ",
1137 "▐▌▗▌█▀▀ ▐▌ █▗ ",
1138 "▀▀▀▘▝▀▘ ▀▀ ▝▘ ",
1139 ]);
1140 assert_eq!(buf, expected);
1141 }
1142
1143 #[test]
1144 fn render_alignment_right() {
1145 let big_text = BigText::builder()
1146 .pixel_size(PixelSize::Quadrant)
1147 .lines(vec![Line::from("Right")])
1148 .alignment(Alignment::Right)
1149 .build();
1150 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 4));
1151 big_text.render(buf.area, &mut buf);
1152 let expected = Buffer::with_lines(vec![
1153 " ▜▛▜▖ ▀ ▜▌ ▟ ",
1154 " ▐▙▟▘▝█ ▟▀▟▘▐▙▜▖▝█▀ ",
1155 " ▐▌▜▖ █ ▜▄█ ▐▌▐▌ █▗ ",
1156 " ▀▘▝▘▝▀▘ ▄▄▛ ▀▘▝▘ ▝▘ ",
1157 ]);
1158 assert_eq!(buf, expected);
1159 }
1160
1161 #[test]
1162 fn render_alignment_center() {
1163 let big_text = BigText::builder()
1164 .pixel_size(PixelSize::Quadrant)
1165 .lines(vec![Line::from("Centered"), Line::from("Lines")])
1166 .alignment(Alignment::Center)
1167 .build();
1168 let mut buf = Buffer::empty(Rect::new(0, 0, 40, 8));
1169 big_text.render(buf.area, &mut buf);
1170 let expected = Buffer::with_lines(vec![
1171 " ▗▛▜▖ ▟ ▝█ ",
1172 " █ ▟▀▙ █▀▙ ▝█▀ ▟▀▙ ▜▟▜▖▟▀▙ ▗▄█ ",
1173 " ▜▖▗▖█▀▀ █ █ █▗ █▀▀ ▐▌▝▘█▀▀ █ █ ",
1174 " ▀▀ ▝▀▘ ▀ ▀ ▝▘ ▝▀▘ ▀▀ ▝▀▘ ▝▀▝▘ ",
1175 " ▜▛ ▀ ",
1176 " ▐▌ ▝█ █▀▙ ▟▀▙ ▟▀▀ ",
1177 " ▐▌▗▌ █ █ █ █▀▀ ▝▀▙ ",
1178 " ▀▀▀▘▝▀▘ ▀ ▀ ▝▀▘ ▀▀▘ ",
1179 ]);
1180 assert_eq!(buf, expected);
1181 }
1182
1183 #[test]
1184 fn render_hiragana_font() {
1185 let big_text = BigText::builder()
1186 .lines(vec![Line::from("ひらがな")])
1187 .build();
1188 let mut buf = Buffer::empty(Rect::new(0, 0, 32, 8));
1189
1190 big_text.render(buf.area, &mut buf);
1191
1192 let expected = Buffer::with_lines(vec![
1193 " ████ █ █ █ ██ ",
1194 " █ █ █ ",
1195 "██ █ █ ████ ███ █ ",
1196 " █ ██ █ ███ █ █ █ █ █ ",
1197 "█ █ █ ██ █ █ █ █ █ ███ ",
1198 "█ █ █ █ █ █ █ █ █ █ ",
1199 " ███ ██ █ █ █ █ ",
1200 " ",
1201 ]);
1202 assert_eq!(buf, expected);
1203 }
1204
1205 #[test]
1206 fn render_greek_font() {
1207 let big_text = BigText::builder()
1208 .lines(vec![Line::from("ελληνικά")])
1209 .build();
1210 let mut buf = Buffer::empty(Rect::new(0, 0, 64, 8));
1211
1212 big_text.render(buf.area, &mut buf);
1213
1214 let expected = Buffer::with_lines(vec![
1215 " ███ ",
1216 " ██ ██ ",
1217 " ████ ██ ██ █████ ██ ██ ██ ██ ██ ███ ██ ",
1218 "██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███ ",
1219 " ███ ███ ███ ██ ██ ██ ██ ██ ████ ██ █ ",
1220 "██ ██ ██ ██ ██ ██ ██ ████ ██ █ ██ ██ ██ ███ ",
1221 " ████ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ ",
1222 " ██ ",
1223 ]);
1224 assert_eq!(buf, expected);
1225 }
1226
1227 #[test]
1228 fn centered_hiragana_uses_glyph_count_for_alignment() {
1229 let line = Line::from("ひらがな");
1230
1231 assert_eq!(get_alignment_offset(80, 8, Alignment::Center, &line), 24);
1232 }
1233
1234 #[test]
1235 fn alignment_width_clamps_to_u16_max() {
1236 let line = Line::from("x".repeat(usize::from(u16::MAX) + 1));
1237
1238 assert_eq!(get_alignment_offset(80, 1, Alignment::Center, &line), 0);
1239 }
1240
1241 #[test]
1242 fn render_with_block() {
1243 let big_text = BigText::builder()
1244 .lines(vec![Line::from("In Block")])
1245 .block(Block::bordered().title("Big Text Block"))
1246 .build();
1247 let mut buf = Buffer::empty(Rect::new(0, 0, 65, 10));
1248 big_text.render(buf.area, &mut buf);
1249 let expected = Buffer::with_lines(vec![
1250 "┌Big Text Block─────────────────────────────────────────────────┐",
1251 "│ ████ ██████ ███ ███ │",
1252 "│ ██ ██ ██ ██ ██ │",
1253 "│ ██ █████ ██ ██ ██ ████ ████ ██ ██│",
1254 "│ ██ ██ ██ █████ ██ ██ ██ ██ ██ ██ ██ │",
1255 "│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ████ │",
1256 "│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ │",
1257 "│ ████ ██ ██ ██████ ████ ████ ████ ███ ██│",
1258 "│ │",
1259 "└───────────────────────────────────────────────────────────────┘",
1260 ]);
1261 assert_eq!(buf, expected);
1262 }
1263}