use super::super::block_chars;
use super::super::{CellRenderer, TextInstance};
use super::ATLAS_SIZE;
use par_term_config::{Cell, color_u8x4_rgb_to_f32_a};
pub(super) struct BlockCharRenderParams<'a> {
pub cell: &'a Cell,
pub ch: char,
pub grapheme_len: usize,
pub x0_pixel: f32,
pub y0_pixel: f32,
pub y1_pixel: f32,
pub render_fg_color: [f32; 4],
pub text_alpha: f32,
pub text_index: usize,
}
impl CellRenderer {
pub(super) fn render_block_char_geometrically(
&mut self,
params: BlockCharRenderParams<'_>,
) -> Option<usize> {
let BlockCharRenderParams {
cell,
ch,
grapheme_len,
x0_pixel: x0,
y0_pixel: y0,
y1_pixel: y1,
render_fg_color,
text_alpha,
mut text_index,
} = params;
let char_type = block_chars::classify_char(ch);
if grapheme_len != 1 || !block_chars::should_render_geometrically(char_type) {
return None;
}
let char_w = if cell.wide_char {
self.grid.cell_width * 2.0
} else {
self.grid.cell_width
};
let snapped_cell_height = y1 - y0;
let solid_tex_offset = [
self.atlas.solid_pixel_offset.0 as f32 / ATLAS_SIZE,
self.atlas.solid_pixel_offset.1 as f32 / ATLAS_SIZE,
];
let solid_tex_size = [1.0 / ATLAS_SIZE, 1.0 / ATLAS_SIZE];
let aspect_ratio = snapped_cell_height / char_w;
if let Some(box_geo) = block_chars::get_box_drawing_geometry(ch, aspect_ratio) {
for segment in &box_geo.segments {
let rect = segment
.to_pixel_rect(x0, y0, char_w, snapped_cell_height)
.snap_to_pixels();
let extension = 1.0;
let ext_x = if segment.x <= 0.01 { extension } else { 0.0 };
let ext_y = if segment.y <= 0.01 { extension } else { 0.0 };
let ext_w = if segment.x + segment.width >= 0.99 {
extension
} else {
0.0
};
let ext_h = if segment.y + segment.height >= 0.99 {
extension
} else {
0.0
};
if text_index < self.buffers.max_text_instances {
self.text_instances[text_index] = TextInstance {
position: [
(rect.x - ext_x) / self.config.width as f32 * 2.0 - 1.0,
1.0 - ((rect.y - ext_y) / self.config.height as f32 * 2.0),
],
size: [
(rect.width + ext_x + ext_w) / self.config.width as f32 * 2.0,
(rect.height + ext_y + ext_h) / self.config.height as f32 * 2.0,
],
tex_offset: solid_tex_offset,
tex_size: solid_tex_size,
color: render_fg_color,
is_colored: 0,
};
text_index += 1;
}
}
return Some(text_index);
}
if ch == '\u{2584}' || ch == '\u{2580}' {
let x1 = x0 + char_w;
let cell_w = x1 - x0;
let y_mid = y0 + self.grid.cell_height / 2.0;
let bg_half_color = color_u8x4_rgb_to_f32_a(cell.bg_color, text_alpha);
let (top_color, bottom_color) = if ch == '\u{2584}' {
(bg_half_color, render_fg_color) } else {
(render_fg_color, bg_half_color) };
if text_index < self.buffers.max_text_instances {
self.text_instances[text_index] = TextInstance {
position: [
x0 / self.config.width as f32 * 2.0 - 1.0,
1.0 - (y0 / self.config.height as f32 * 2.0),
],
size: [
cell_w / self.config.width as f32 * 2.0,
(y_mid - y0) / self.config.height as f32 * 2.0,
],
tex_offset: solid_tex_offset,
tex_size: solid_tex_size,
color: top_color,
is_colored: 0,
};
text_index += 1;
}
if text_index < self.buffers.max_text_instances {
self.text_instances[text_index] = TextInstance {
position: [
x0 / self.config.width as f32 * 2.0 - 1.0,
1.0 - (y_mid / self.config.height as f32 * 2.0),
],
size: [
cell_w / self.config.width as f32 * 2.0,
(y1 - y_mid) / self.config.height as f32 * 2.0,
],
tex_offset: solid_tex_offset,
tex_size: solid_tex_size,
color: bottom_color,
is_colored: 0,
};
text_index += 1;
}
return Some(text_index);
}
if let Some(rect) =
block_chars::get_geometric_shape_rect(ch, x0, y0, char_w, snapped_cell_height)
{
if text_index < self.buffers.max_text_instances {
self.text_instances[text_index] = TextInstance {
position: [
rect.x / self.config.width as f32 * 2.0 - 1.0,
1.0 - (rect.y / self.config.height as f32 * 2.0),
],
size: [
rect.width / self.config.width as f32 * 2.0,
rect.height / self.config.height as f32 * 2.0,
],
tex_offset: solid_tex_offset,
tex_size: solid_tex_size,
color: render_fg_color,
is_colored: 0,
};
text_index += 1;
}
return Some(text_index);
}
if let Some(geo_block) = block_chars::get_geometric_block(ch) {
let rect = geo_block.to_pixel_rect(x0, y0, char_w, self.grid.cell_height);
let extension = 1.0;
let ext_x = if geo_block.x == 0.0 { extension } else { 0.0 };
let ext_y = if geo_block.y == 0.0 { extension } else { 0.0 };
let ext_w = if geo_block.x + geo_block.width >= 1.0 {
extension
} else {
0.0
};
let ext_h = if geo_block.y + geo_block.height >= 1.0 {
extension
} else {
0.0
};
if text_index < self.buffers.max_text_instances {
self.text_instances[text_index] = TextInstance {
position: [
(rect.x - ext_x) / self.config.width as f32 * 2.0 - 1.0,
1.0 - ((rect.y - ext_y) / self.config.height as f32 * 2.0),
],
size: [
(rect.width + ext_x + ext_w) / self.config.width as f32 * 2.0,
(rect.height + ext_y + ext_h) / self.config.height as f32 * 2.0,
],
tex_offset: solid_tex_offset,
tex_size: solid_tex_size,
color: render_fg_color,
is_colored: 0,
};
text_index += 1;
}
return Some(text_index);
}
None
}
}