Fix multiple underlines/strikeouts on the same line
This commit fixes regression introduced in ddee14a
.
This commit is contained in:
parent
14fa02648e
commit
b20d285782
|
@ -27,7 +27,7 @@ use crate::config::{Config, StartupMode};
|
||||||
use crate::index::Line;
|
use crate::index::Line;
|
||||||
use crate::message_bar::Message;
|
use crate::message_bar::Message;
|
||||||
use crate::meter::Meter;
|
use crate::meter::Meter;
|
||||||
use crate::renderer::rects::{Rect, Rects};
|
use crate::renderer::rects::{RenderRect, RenderLines};
|
||||||
use crate::renderer::{self, GlyphCache, QuadRenderer};
|
use crate::renderer::{self, GlyphCache, QuadRenderer};
|
||||||
use crate::sync::FairMutex;
|
use crate::sync::FairMutex;
|
||||||
use crate::term::color::Rgb;
|
use crate::term::color::Rgb;
|
||||||
|
@ -511,7 +511,7 @@ impl Display {
|
||||||
|
|
||||||
{
|
{
|
||||||
let glyph_cache = &mut self.glyph_cache;
|
let glyph_cache = &mut self.glyph_cache;
|
||||||
let mut rects = Rects::new();
|
let mut lines = RenderLines::new();
|
||||||
|
|
||||||
// Draw grid
|
// Draw grid
|
||||||
{
|
{
|
||||||
|
@ -521,7 +521,7 @@ impl Display {
|
||||||
// Iterate over all non-empty cells in the grid
|
// Iterate over all non-empty cells in the grid
|
||||||
for cell in grid_cells {
|
for cell in grid_cells {
|
||||||
// Update underline/strikeout
|
// Update underline/strikeout
|
||||||
rects.update_lines(&cell, &size_info, &metrics);
|
lines.update(&cell);
|
||||||
|
|
||||||
// Draw the cell
|
// Draw the cell
|
||||||
api.render_cell(cell, glyph_cache);
|
api.render_cell(cell, glyph_cache);
|
||||||
|
@ -529,14 +529,21 @@ impl Display {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut rects = lines.into_rects(&metrics, &size_info);
|
||||||
|
|
||||||
if let Some(message) = message_buffer {
|
if let Some(message) = message_buffer {
|
||||||
let text = message.text(&size_info);
|
let text = message.text(&size_info);
|
||||||
|
|
||||||
// Create a new rectangle for the background
|
// Create a new rectangle for the background
|
||||||
let start_line = size_info.lines().0 - text.len();
|
let start_line = size_info.lines().0 - text.len();
|
||||||
let y = size_info.padding_y + size_info.cell_height * start_line as f32;
|
let y = size_info.padding_y + size_info.cell_height * start_line as f32;
|
||||||
let rect = Rect::new(0., y, size_info.width, size_info.height - y);
|
rects.push(RenderRect::new(
|
||||||
rects.push(rect, message.color());
|
0.,
|
||||||
|
y,
|
||||||
|
size_info.width,
|
||||||
|
size_info.height - y,
|
||||||
|
message.color(),
|
||||||
|
));
|
||||||
|
|
||||||
// Draw rectangles including the new background
|
// Draw rectangles including the new background
|
||||||
self.renderer.draw_rects(config, &size_info, visual_bell_intensity, rects);
|
self.renderer.draw_rects(config, &size_info, visual_bell_intensity, rects);
|
||||||
|
|
|
@ -31,7 +31,7 @@ use crate::cursor::{get_cursor_glyph, CursorKey};
|
||||||
use crate::gl;
|
use crate::gl;
|
||||||
use crate::gl::types::*;
|
use crate::gl::types::*;
|
||||||
use crate::index::{Column, Line};
|
use crate::index::{Column, Line};
|
||||||
use crate::renderer::rects::{Rect, Rects};
|
use crate::renderer::rects::RenderRect;
|
||||||
use crate::term::color::Rgb;
|
use crate::term::color::Rgb;
|
||||||
use crate::term::{self, cell, RenderableCell, RenderableCellContent};
|
use crate::term::{self, cell, RenderableCell, RenderableCellContent};
|
||||||
|
|
||||||
|
@ -679,7 +679,7 @@ impl QuadRenderer {
|
||||||
config: &Config,
|
config: &Config,
|
||||||
props: &term::SizeInfo,
|
props: &term::SizeInfo,
|
||||||
visual_bell_intensity: f64,
|
visual_bell_intensity: f64,
|
||||||
cell_line_rects: Rects,
|
cell_line_rects: Vec<RenderRect>,
|
||||||
) {
|
) {
|
||||||
// Swap to rectangle rendering program
|
// Swap to rectangle rendering program
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -710,12 +710,12 @@ impl QuadRenderer {
|
||||||
|
|
||||||
// Draw visual bell
|
// Draw visual bell
|
||||||
let color = config.visual_bell.color;
|
let color = config.visual_bell.color;
|
||||||
let rect = Rect::new(0., 0., props.width, props.height);
|
let rect = RenderRect::new(0., 0., props.width, props.height, color);
|
||||||
self.render_rect(&rect, color, visual_bell_intensity as f32, props);
|
self.render_rect(&rect, visual_bell_intensity as f32, props);
|
||||||
|
|
||||||
// Draw underlines and strikeouts
|
// Draw underlines and strikeouts
|
||||||
for cell_line_rect in cell_line_rects.rects() {
|
for cell_line_rect in cell_line_rects {
|
||||||
self.render_rect(&cell_line_rect.0, cell_line_rect.1, 255., props);
|
self.render_rect(&cell_line_rect, 255., props);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deactivate rectangle program again
|
// Deactivate rectangle program again
|
||||||
|
@ -849,7 +849,7 @@ impl QuadRenderer {
|
||||||
// Render a rectangle
|
// Render a rectangle
|
||||||
//
|
//
|
||||||
// This requires the rectangle program to be activated
|
// This requires the rectangle program to be activated
|
||||||
fn render_rect(&mut self, rect: &Rect<f32>, color: Rgb, alpha: f32, size: &term::SizeInfo) {
|
fn render_rect(&mut self, rect: &RenderRect, alpha: f32, size: &term::SizeInfo) {
|
||||||
// Do nothing when alpha is fully transparent
|
// Do nothing when alpha is fully transparent
|
||||||
if alpha == 0. {
|
if alpha == 0. {
|
||||||
return;
|
return;
|
||||||
|
@ -876,7 +876,7 @@ impl QuadRenderer {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Color
|
// Color
|
||||||
self.rect_program.set_color(color, alpha);
|
self.rect_program.set_color(rect.color, alpha);
|
||||||
|
|
||||||
// Draw the rectangle
|
// Draw the rectangle
|
||||||
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
|
gl::DrawElements(gl::TRIANGLES, 6, gl::UNSIGNED_INT, ptr::null());
|
||||||
|
|
|
@ -21,29 +21,31 @@ use crate::term::color::Rgb;
|
||||||
use crate::term::{RenderableCell, SizeInfo};
|
use crate::term::{RenderableCell, SizeInfo};
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct Rect<T> {
|
pub struct RenderRect {
|
||||||
pub x: T,
|
pub x: f32,
|
||||||
pub y: T,
|
pub y: f32,
|
||||||
pub width: T,
|
pub width: f32,
|
||||||
pub height: T,
|
pub height: f32,
|
||||||
|
pub color: Rgb,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Rect<T> {
|
impl RenderRect {
|
||||||
pub fn new(x: T, y: T, width: T, height: T) -> Self {
|
pub fn new(x: f32, y: f32, width: f32, height: f32, color: Rgb) -> Self {
|
||||||
Rect { x, y, width, height }
|
RenderRect { x, y, width, height, color }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Line {
|
struct RenderLine {
|
||||||
rect: Rect<f32>,
|
|
||||||
start: Point,
|
start: Point,
|
||||||
|
end: Point,
|
||||||
color: Rgb,
|
color: Rgb,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Line {
|
impl RenderLine {
|
||||||
/// Create a line that starts on the left of `cell` and is one cell wide
|
fn into_rect(self, flag: Flags, metrics: &Metrics, size: &SizeInfo) -> RenderRect {
|
||||||
fn from_cell(cell: &RenderableCell, flag: Flags, metrics: &Metrics, size: &SizeInfo) -> Line {
|
let start_x = self.start.col.0 as f32 * size.cell_width;
|
||||||
let cell_x = cell.column.0 as f32 * size.cell_width;
|
let end_x = (self.end.col.0 + 1) as f32 * size.cell_width;
|
||||||
|
let width = end_x - start_x;
|
||||||
|
|
||||||
let (position, mut height) = match flag {
|
let (position, mut height) = match flag {
|
||||||
Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness),
|
Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness),
|
||||||
|
@ -54,48 +56,42 @@ impl Line {
|
||||||
// Make sure lines are always visible
|
// Make sure lines are always visible
|
||||||
height = height.max(1.);
|
height = height.max(1.);
|
||||||
|
|
||||||
let cell_bottom = (cell.line.0 as f32 + 1.) * size.cell_height;
|
let line_bottom = (self.start.line.0 as f32 + 1.) * size.cell_height;
|
||||||
let baseline = cell_bottom + metrics.descent;
|
let baseline = line_bottom + metrics.descent;
|
||||||
|
|
||||||
let mut y = baseline - position - height / 2.;
|
let mut y = baseline - position - height / 2.;
|
||||||
let max_y = cell_bottom - height;
|
let max_y = line_bottom - height;
|
||||||
if y > max_y {
|
if y > max_y {
|
||||||
y = max_y;
|
y = max_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rect = Rect::new(cell_x + size.padding_x, y + size.padding_y, size.cell_width, height);
|
RenderRect::new(start_x + size.padding_x, y + size.padding_y, width, height, self.color)
|
||||||
|
|
||||||
Self { start: cell.into(), color: cell.fg, rect }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update_end(&mut self, end: Point, size: &SizeInfo) {
|
|
||||||
self.rect.width = (end.col + 1 - self.start.col).0 as f32 * size.cell_width;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rects for underline, strikeout and more.
|
/// Lines for underline and strikeout.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Rects {
|
pub struct RenderLines {
|
||||||
inner: HashMap<Flags, Vec<Line>>,
|
inner: HashMap<Flags, Vec<RenderLine>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Rects {
|
impl RenderLines {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self::default()
|
Self::default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert the stored rects to rectangles for the renderer.
|
pub fn into_rects(self, metrics: &Metrics, size: &SizeInfo) -> Vec<RenderRect> {
|
||||||
pub fn rects(&self) -> Vec<(Rect<f32>, Rgb)> {
|
|
||||||
self.inner
|
self.inner
|
||||||
.iter()
|
.into_iter()
|
||||||
.map(|(_, lines)| lines)
|
.map(|(flag, lines)| -> Vec<RenderRect> {
|
||||||
|
lines.into_iter().map(|line| line.into_rect(flag, &metrics, &size)).collect()
|
||||||
|
})
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|line| (line.rect, line.color))
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the stored lines with the next cell info.
|
/// Update the stored lines with the next cell info.
|
||||||
pub fn update_lines(&mut self, cell: &RenderableCell, size: &SizeInfo, metrics: &Metrics) {
|
pub fn update(&mut self, cell: &RenderableCell) {
|
||||||
for flag in &[Flags::UNDERLINE, Flags::STRIKEOUT] {
|
for flag in &[Flags::UNDERLINE, Flags::STRIKEOUT] {
|
||||||
if !cell.flags.contains(*flag) {
|
if !cell.flags.contains(*flag) {
|
||||||
continue;
|
continue;
|
||||||
|
@ -103,35 +99,24 @@ impl Rects {
|
||||||
|
|
||||||
// Check if there's an active line
|
// Check if there's an active line
|
||||||
if let Some(line) = self.inner.get_mut(flag).and_then(|lines| lines.last_mut()) {
|
if let Some(line) = self.inner.get_mut(flag).and_then(|lines| lines.last_mut()) {
|
||||||
if cell.line == line.start.line && cell.fg == line.color {
|
if cell.line == line.start.line
|
||||||
|
&& cell.fg == line.color
|
||||||
|
&& cell.column == line.end.col + 1
|
||||||
|
{
|
||||||
// Update the length of the line
|
// Update the length of the line
|
||||||
line.update_end(cell.into(), size);
|
line.end = cell.into();
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start new line if there currently is none
|
// Start new line if there currently is none
|
||||||
let rect = Line::from_cell(cell, *flag, metrics, size);
|
let line = RenderLine { start: cell.into(), end: cell.into(), color: cell.fg };
|
||||||
match self.inner.get_mut(flag) {
|
match self.inner.get_mut(flag) {
|
||||||
Some(lines) => lines.push(rect),
|
Some(lines) => lines.push(line),
|
||||||
None => {
|
None => {
|
||||||
self.inner.insert(*flag, vec![rect]);
|
self.inner.insert(*flag, vec![line]);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a rectangle
|
|
||||||
pub fn push(&mut self, rect: Rect<f32>, color: Rgb) {
|
|
||||||
let line = Line { start: Point::default(), color, rect };
|
|
||||||
|
|
||||||
// Flag `HIDDEN` for hashmap index is arbitrary
|
|
||||||
match self.inner.get_mut(&Flags::HIDDEN) {
|
|
||||||
Some(lines) => lines.push(line),
|
|
||||||
None => {
|
|
||||||
self.inner.insert(Flags::HIDDEN, vec![line]);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue