//! Hand-rolled drawing of unicode [box drawing](http://www.unicode.org/charts/PDF/U2500.pdf)
//! and [block elements](https://www.unicode.org/charts/PDF/U2580.pdf), and also powerline symbols.
use std::{cmp, mem, ops};
use crossfont::{BitmapBuffer, Metrics, RasterizedGlyph};
use crate::config::ui_config::Delta;
// Colors which are used for filling shade variants.
const COLOR_FILL_ALPHA_STEP_1: Pixel = Pixel { _r: 192, _g: 192, _b: 192 };
const COLOR_FILL_ALPHA_STEP_2: Pixel = Pixel { _r: 128, _g: 128, _b: 128 };
const COLOR_FILL_ALPHA_STEP_3: Pixel = Pixel { _r: 64, _g: 64, _b: 64 };
/// Default color used for filling.
const COLOR_FILL: Pixel = Pixel { _r: 255, _g: 255, _b: 255 };
const POWERLINE_TRIANGLE_LTR: char = '\u{e0b0}';
const POWERLINE_ARROW_LTR: char = '\u{e0b1}';
const POWERLINE_TRIANGLE_RTL: char = '\u{e0b2}';
const POWERLINE_ARROW_RTL: char = '\u{e0b3}';
/// Returns the rasterized glyph if the character is part of the built-in font.
pub fn builtin_glyph(
character: char,
metrics: &Metrics,
offset: &Delta<i8>,
glyph_offset: &Delta<i8>,
) -> Option<RasterizedGlyph> {
let mut glyph = match character {
// Box drawing characters and block elements.
'\u{2500}'..='\u{259f}' => box_drawing(character, metrics, offset),
// Powerline symbols: '','','',''
POWERLINE_TRIANGLE_LTR..=POWERLINE_ARROW_RTL => {
powerline_drawing(character, metrics, offset)?
},
_ => return None,
};
// Since we want to ignore `glyph_offset` for the built-in font, subtract it to compensate its
// addition when loading glyphs in the renderer.
glyph.left -= glyph_offset.x as i32;
glyph.top -= glyph_offset.y as i32;
Some(glyph)
}
fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> RasterizedGlyph {
// Ensure that width and height is at least one.
let height = (metrics.line_height as i32 + offset.y as i32).max(1) as usize;
let width = (metrics.average_advance as i32 + offset.x as i32).max(1) as usize;
let stroke_size = calculate_stroke_size(width);
let heavy_stroke_size = stroke_size * 2;
// Certain symbols require larger canvas than the cell itself, since for proper contiguous
// lines they require drawing on neighbour cells. So treat them specially early on and handle
// 'normal' characters later.
let mut canvas = match character {
// Diagonals: '╱', '╲', '╳'.
'\u{2571}'..='\u{2573}' => {
// Last coordinates.
let x_end = width as f32;
let mut y_end = height as f32;
let top = height as i32 + metrics.descent as i32 + stroke_size as i32;
let height = height + 2 * stroke_size;
let mut canvas = Canvas::new(width, height + 2 * stroke_size);
// The offset that we should take into account when drawing, since we've enlarged
// buffer vertically by twice of that amount.
let y_offset = stroke_size as f32;
y_end += y_offset;
let k = y_end / x_end;
let f_x = |x: f32, h: f32| -> f32 { -1. * k * x + h + y_offset };
let g_x = |x: f32, h: f32| -> f32 { k * x + h + y_offset };
let from_x = 0.;
let to_x = x_end + 1.;
for stroke_size in 0..2 * stroke_size {
let stroke_size = stroke_size as f32 / 2.;
if character == '\u{2571}' || character == '\u{2573}' {