Add proper underline and strikeout support
This makes use of the new rectangle rendering methods used to display the colored visual bell to add proper underline and strikeout support to Alacritty.
This commit is contained in:
parent
dad44134e2
commit
2f9b815ebd
|
@ -430,10 +430,25 @@ impl Font {
|
||||||
let leading = self.ct_font.leading() as f64;
|
let leading = self.ct_font.leading() as f64;
|
||||||
let line_height = (ascent + descent + leading + 0.5).floor();
|
let line_height = (ascent + descent + leading + 0.5).floor();
|
||||||
|
|
||||||
|
// Strikeout and underline metrics
|
||||||
|
// CoreText doesn't provide strikeout so we provide our own
|
||||||
|
let underline_position =
|
||||||
|
(self.ct_font.underline_position() - descent)
|
||||||
|
.round() as f32;
|
||||||
|
let underline_thickness = self.ct_font.underline_thickness()
|
||||||
|
.round()
|
||||||
|
.max(1.) as f32;
|
||||||
|
let strikeout_position = (line_height as f32 / 2. - descent as f32).round();
|
||||||
|
let strikeout_thickness = underline_thickness;
|
||||||
|
|
||||||
Metrics {
|
Metrics {
|
||||||
average_advance,
|
average_advance,
|
||||||
line_height,
|
line_height,
|
||||||
descent: -(self.ct_font.descent() as f32),
|
descent: -(self.ct_font.descent() as f32),
|
||||||
|
underline_position,
|
||||||
|
underline_thickness,
|
||||||
|
strikeout_position,
|
||||||
|
strikeout_thickness,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ use std::cmp::min;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
use freetype::tt_os2::TrueTypeOS2Table;
|
||||||
use freetype::{self, Library};
|
use freetype::{self, Library};
|
||||||
use libc::c_uint;
|
use libc::c_uint;
|
||||||
|
|
||||||
|
@ -86,15 +87,50 @@ impl ::Rasterize for FreeTypeRasterizer {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metrics(&self, key: FontKey, _size: Size) -> Result<Metrics, Error> {
|
fn metrics(&self, key: FontKey, _size: Size) -> Result<Metrics, Error> {
|
||||||
|
let face = self.faces
|
||||||
|
.get(&key)
|
||||||
|
.ok_or(Error::FontNotLoaded)?;
|
||||||
let full = self.full_metrics(key)?;
|
let full = self.full_metrics(key)?;
|
||||||
|
|
||||||
let height = (full.size_metrics.height / 64) as f64;
|
let height = (full.size_metrics.height / 64) as f64;
|
||||||
let descent = (full.size_metrics.descender / 64) as f32;
|
let descent = (full.size_metrics.descender / 64) as f32;
|
||||||
|
|
||||||
|
// Get underline position and thickness in device pixels
|
||||||
|
let x_scale = full.size_metrics.x_scale as f32 / 65536.0;
|
||||||
|
let underline_position =
|
||||||
|
(f32::from(face.ft_face.underline_position()) * x_scale / 64.).round();
|
||||||
|
let underline_thickness =
|
||||||
|
(f32::from(face.ft_face.underline_thickness()) * x_scale / 64.)
|
||||||
|
.round()
|
||||||
|
.max(1.);
|
||||||
|
|
||||||
|
// Get strikeout position and thickness in device pixels
|
||||||
|
let (strikeout_position, strikeout_thickness) =
|
||||||
|
match TrueTypeOS2Table::from_face(&mut face.ft_face.clone())
|
||||||
|
{
|
||||||
|
Some(os2) => {
|
||||||
|
let strikeout_position =
|
||||||
|
(f32::from(os2.y_strikeout_position()) * x_scale / 64.).round();
|
||||||
|
let strikeout_thickness =
|
||||||
|
(f32::from(os2.y_strikeout_size()) * x_scale / 64.).round();
|
||||||
|
(strikeout_position, strikeout_thickness)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
// Fallback if font doesn't provide info about strikeout
|
||||||
|
trace!("No strikeout data available for font, using fallback.");
|
||||||
|
let strikeout_position = height as f32 / 2. + descent;
|
||||||
|
(strikeout_position, underline_thickness)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
Ok(Metrics {
|
Ok(Metrics {
|
||||||
average_advance: full.cell_width,
|
average_advance: full.cell_width,
|
||||||
line_height: height,
|
line_height: height,
|
||||||
descent,
|
descent,
|
||||||
|
underline_position,
|
||||||
|
underline_thickness,
|
||||||
|
strikeout_position,
|
||||||
|
strikeout_thickness,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -336,6 +336,10 @@ pub struct Metrics {
|
||||||
pub average_advance: f64,
|
pub average_advance: f64,
|
||||||
pub line_height: f64,
|
pub line_height: f64,
|
||||||
pub descent: f32,
|
pub descent: f32,
|
||||||
|
pub underline_position: f32,
|
||||||
|
pub underline_thickness: f32,
|
||||||
|
pub strikeout_position: f32,
|
||||||
|
pub strikeout_thickness: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Rasterize {
|
pub trait Rasterize {
|
||||||
|
|
|
@ -33,10 +33,25 @@ impl crate::Rasterize for RustTypeRasterizer {
|
||||||
.ok_or(Error::MissingGlyph)?
|
.ok_or(Error::MissingGlyph)?
|
||||||
.scaled(scale)
|
.scaled(scale)
|
||||||
.h_metrics();
|
.h_metrics();
|
||||||
|
|
||||||
|
let line_height = f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap);
|
||||||
|
let average_advance = f64::from(hmetrics.advance_width);
|
||||||
|
let descent = vmetrics.descent;
|
||||||
|
|
||||||
|
// Strikeout and underline metrics
|
||||||
|
// RustType doesn't support these, so we make up our own
|
||||||
|
let thickness = (descent / 5.).round();
|
||||||
|
let underline_position = descent / 2. + thickness / 2.;
|
||||||
|
let strikeout_position = (line_height as f32 / 2. - descent).round();
|
||||||
|
|
||||||
Ok(Metrics {
|
Ok(Metrics {
|
||||||
descent: vmetrics.descent,
|
descent,
|
||||||
average_advance: f64::from(hmetrics.advance_width),
|
average_advance,
|
||||||
line_height: f64::from(vmetrics.ascent - vmetrics.descent + vmetrics.line_gap),
|
line_height,
|
||||||
|
underline_position,
|
||||||
|
underline_thickness: thickness,
|
||||||
|
strikeout_position,
|
||||||
|
strikeout_thickness: thickness,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -642,7 +642,7 @@ pub enum Attr {
|
||||||
Reverse,
|
Reverse,
|
||||||
/// Do not display characters
|
/// Do not display characters
|
||||||
Hidden,
|
Hidden,
|
||||||
/// Strikethrough text
|
/// Strikeout text
|
||||||
Strike,
|
Strike,
|
||||||
/// Cancel bold
|
/// Cancel bold
|
||||||
CancelBold,
|
CancelBold,
|
||||||
|
@ -658,7 +658,7 @@ pub enum Attr {
|
||||||
CancelReverse,
|
CancelReverse,
|
||||||
/// Cancel text hiding
|
/// Cancel text hiding
|
||||||
CancelHidden,
|
CancelHidden,
|
||||||
/// Cancel strike through
|
/// Cancel strikeout
|
||||||
CancelStrike,
|
CancelStrike,
|
||||||
/// Set indexed foreground color
|
/// Set indexed foreground color
|
||||||
Foreground(Color),
|
Foreground(Color),
|
||||||
|
|
|
@ -25,6 +25,7 @@ use crate::config::Config;
|
||||||
use font::{self, Rasterize};
|
use font::{self, Rasterize};
|
||||||
use crate::meter::Meter;
|
use crate::meter::Meter;
|
||||||
use crate::renderer::{self, GlyphCache, QuadRenderer};
|
use crate::renderer::{self, GlyphCache, QuadRenderer};
|
||||||
|
use crate::renderer::lines::Lines;
|
||||||
use crate::term::{Term, SizeInfo, RenderableCell};
|
use crate::term::{Term, SizeInfo, RenderableCell};
|
||||||
use crate::sync::FairMutex;
|
use crate::sync::FairMutex;
|
||||||
use crate::window::{self, Window};
|
use crate::window::{self, Window};
|
||||||
|
@ -410,19 +411,27 @@ impl Display {
|
||||||
|
|
||||||
{
|
{
|
||||||
let glyph_cache = &mut self.glyph_cache;
|
let glyph_cache = &mut self.glyph_cache;
|
||||||
|
let metrics = glyph_cache.font_metrics();
|
||||||
|
let mut cell_line_rects = Lines::new(&metrics, &size_info);
|
||||||
|
|
||||||
// Draw grid
|
// Draw grid
|
||||||
{
|
{
|
||||||
let _sampler = self.meter.sampler();
|
let _sampler = self.meter.sampler();
|
||||||
|
|
||||||
self.renderer.with_api(config, &size_info, |mut api| {
|
self.renderer.with_api(config, &size_info, |mut api| {
|
||||||
// Draw the grid
|
// Iterate over all non-empty cells in the grid
|
||||||
api.render_cells(grid_cells.iter(), glyph_cache);
|
for cell in grid_cells {
|
||||||
|
// Update underline/strikeout
|
||||||
|
cell_line_rects.update_lines(&cell);
|
||||||
|
|
||||||
|
// Draw the cell
|
||||||
|
api.render_cell(cell, glyph_cache);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw rectangles
|
// Draw rectangles
|
||||||
self.renderer.draw_rects(config, &size_info, visual_bell_intensity);
|
self.renderer.draw_rects(config, &size_info, visual_bell_intensity, cell_line_rects);
|
||||||
|
|
||||||
// Draw render timer
|
// Draw render timer
|
||||||
if self.render_timer {
|
if self.render_timer {
|
||||||
|
@ -490,4 +499,3 @@ impl Display {
|
||||||
self.window().set_ime_spot(LogicalPosition::from((nspot_x, nspot_y)));
|
self.window().set_ime_spot(LogicalPosition::from((nspot_x, nspot_y)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::term::{ SizeInfo, RenderableCell};
|
||||||
|
use crate::term::cell::Flags;
|
||||||
|
use crate::renderer::Rect;
|
||||||
|
use font::Metrics;
|
||||||
|
use crate::Rgb;
|
||||||
|
|
||||||
|
/// Lines for underline and strikeout.
|
||||||
|
pub struct Lines<'a> {
|
||||||
|
inner: Vec<(Rect<f32>, Rgb)>,
|
||||||
|
last_starts: HashMap<Flags, Option<RenderableCell>>,
|
||||||
|
last_cell: Option<RenderableCell>,
|
||||||
|
metrics: &'a Metrics,
|
||||||
|
size: &'a SizeInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Lines<'a> {
|
||||||
|
pub fn new(metrics: &'a Metrics, size: &'a SizeInfo) -> Self {
|
||||||
|
let mut last_starts = HashMap::new();
|
||||||
|
last_starts.insert(Flags::UNDERLINE, None);
|
||||||
|
last_starts.insert(Flags::STRIKEOUT, None);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
inner: Vec::new(),
|
||||||
|
last_cell: None,
|
||||||
|
last_starts,
|
||||||
|
metrics,
|
||||||
|
size,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert the stored lines to rectangles for the renderer.
|
||||||
|
pub fn rects(mut self) -> Vec<(Rect<f32>, Rgb)> {
|
||||||
|
// If there's still a line pending, draw it until the last cell
|
||||||
|
for (flag, start_cell) in self.last_starts.iter_mut() {
|
||||||
|
if let Some(start) = start_cell {
|
||||||
|
self.inner.push(
|
||||||
|
create_rect(
|
||||||
|
&start,
|
||||||
|
&self.last_cell.unwrap(),
|
||||||
|
*flag,
|
||||||
|
&self.metrics,
|
||||||
|
&self.size,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update the stored lines with the next cell info.
|
||||||
|
pub fn update_lines(&mut self, cell: &RenderableCell) {
|
||||||
|
for (flag, start_cell) in self.last_starts.iter_mut() {
|
||||||
|
let flag = *flag;
|
||||||
|
*start_cell = match *start_cell {
|
||||||
|
// Check for end if line is present
|
||||||
|
Some(ref mut start) => {
|
||||||
|
// No change in line
|
||||||
|
if cell.line == start.line && cell.flags.contains(flag) && cell.fg == start.fg {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inner.push(
|
||||||
|
create_rect(
|
||||||
|
&start,
|
||||||
|
&self.last_cell.unwrap(),
|
||||||
|
flag,
|
||||||
|
&self.metrics,
|
||||||
|
&self.size,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Start a new line if the flag is present
|
||||||
|
if cell.flags.contains(flag) {
|
||||||
|
Some(*cell)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check for new start of line
|
||||||
|
None => if cell.flags.contains(flag) {
|
||||||
|
Some(*cell)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.last_cell = Some(*cell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a rectangle between two cells.
|
||||||
|
fn create_rect(
|
||||||
|
start: &RenderableCell,
|
||||||
|
end: &RenderableCell,
|
||||||
|
flag: Flags,
|
||||||
|
metrics: &Metrics,
|
||||||
|
size: &SizeInfo,
|
||||||
|
) -> (Rect<f32>, Rgb) {
|
||||||
|
let start_x = start.column.0 as f32 * size.cell_width;
|
||||||
|
let end_x = (end.column.0 + 1) as f32 * size.cell_width;
|
||||||
|
let width = end_x - start_x;
|
||||||
|
|
||||||
|
let (position, height) = match flag {
|
||||||
|
Flags::UNDERLINE => (metrics.underline_position, metrics.underline_thickness),
|
||||||
|
Flags::STRIKEOUT => (metrics.strikeout_position, metrics.strikeout_thickness),
|
||||||
|
_ => unimplemented!("Invalid flag for cell line drawing specified"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let cell_bottom = (start.line.0 as f32 + 1.) * size.cell_height;
|
||||||
|
let baseline = cell_bottom + metrics.descent;
|
||||||
|
|
||||||
|
let mut y = baseline - position - height / 2.;
|
||||||
|
let max_y = cell_bottom - height;
|
||||||
|
if y > max_y {
|
||||||
|
y = max_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
let rect = Rect::new(
|
||||||
|
start_x + size.padding_x,
|
||||||
|
y + size.padding_y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
);
|
||||||
|
|
||||||
|
(rect, start.fg)
|
||||||
|
}
|
|
@ -23,16 +23,19 @@ use std::time::Duration;
|
||||||
|
|
||||||
use cgmath;
|
use cgmath;
|
||||||
use fnv::FnvHasher;
|
use fnv::FnvHasher;
|
||||||
|
use glutin::dpi::PhysicalSize;
|
||||||
use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer};
|
use font::{self, FontDesc, FontKey, GlyphKey, Rasterize, RasterizedGlyph, Rasterizer};
|
||||||
|
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
||||||
|
|
||||||
use crate::gl::types::*;
|
use crate::gl::types::*;
|
||||||
use crate::gl;
|
use crate::gl;
|
||||||
use crate::index::{Column, Line, RangeInclusive};
|
use crate::index::{Column, Line, RangeInclusive};
|
||||||
use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher};
|
|
||||||
use crate::Rgb;
|
use crate::Rgb;
|
||||||
|
|
||||||
use crate::config::{self, Config, Delta};
|
use crate::config::{self, Config, Delta};
|
||||||
use crate::term::{self, cell, RenderableCell};
|
use crate::term::{self, cell, RenderableCell};
|
||||||
use glutin::dpi::PhysicalSize;
|
use crate::renderer::lines::Lines;
|
||||||
|
|
||||||
|
pub mod lines;
|
||||||
|
|
||||||
// Shader paths for live reload
|
// Shader paths for live reload
|
||||||
static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");
|
static TEXT_SHADER_F_PATH: &'static str = concat!(env!("CARGO_MANIFEST_DIR"), "/res/text.f.glsl");
|
||||||
|
@ -699,6 +702,7 @@ impl QuadRenderer {
|
||||||
config: &Config,
|
config: &Config,
|
||||||
props: &term::SizeInfo,
|
props: &term::SizeInfo,
|
||||||
visual_bell_intensity: f64,
|
visual_bell_intensity: f64,
|
||||||
|
cell_line_rects: Lines,
|
||||||
) {
|
) {
|
||||||
// Swap to rectangle rendering program
|
// Swap to rectangle rendering program
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -725,6 +729,11 @@ impl QuadRenderer {
|
||||||
let rect = Rect::new(0., 0., props.width, props.height);
|
let rect = Rect::new(0., 0., props.width, props.height);
|
||||||
self.render_rect(&rect, color, visual_bell_intensity as f32, props);
|
self.render_rect(&rect, color, visual_bell_intensity as f32, props);
|
||||||
|
|
||||||
|
// Draw underlines and strikeouts
|
||||||
|
for cell_line_rect in cell_line_rects.rects() {
|
||||||
|
self.render_rect(&cell_line_rect.0, cell_line_rect.1, 255., props);
|
||||||
|
}
|
||||||
|
|
||||||
// Deactivate rectangle program again
|
// Deactivate rectangle program again
|
||||||
unsafe {
|
unsafe {
|
||||||
// Reset blending strategy
|
// Reset blending strategy
|
||||||
|
@ -902,7 +911,8 @@ impl QuadRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Rect<T> {
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub struct Rect<T> {
|
||||||
x: T,
|
x: T,
|
||||||
y: T,
|
y: T,
|
||||||
width: T,
|
width: T,
|
||||||
|
@ -910,7 +920,7 @@ struct Rect<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Rect<T> {
|
impl<T> Rect<T> {
|
||||||
fn new(x: T, y: T, width: T, height: T) -> Self {
|
pub fn new(x: T, y: T, width: T, height: T) -> Self {
|
||||||
Rect { x, y, width, height }
|
Rect { x, y, width, height }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -998,7 +1008,9 @@ impl<'a> RenderApi<'a> {
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
self.render_cells(cells.iter(), glyph_cache);
|
for cell in cells {
|
||||||
|
self.render_cell(cell, glyph_cache);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1016,14 +1028,7 @@ impl<'a> RenderApi<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn render_cells<'b, I>(
|
pub fn render_cell(&mut self, cell: RenderableCell, glyph_cache: &mut GlyphCache) {
|
||||||
&mut self,
|
|
||||||
cells: I,
|
|
||||||
glyph_cache: &mut GlyphCache
|
|
||||||
)
|
|
||||||
where I: Iterator<Item=&'b RenderableCell>
|
|
||||||
{
|
|
||||||
for cell in cells {
|
|
||||||
// Get font key for cell
|
// Get font key for cell
|
||||||
// FIXME this is super inefficient.
|
// FIXME this is super inefficient.
|
||||||
let font_key = if cell.flags.contains(cell::Flags::BOLD) {
|
let font_key = if cell.flags.contains(cell::Flags::BOLD) {
|
||||||
|
@ -1070,21 +1075,6 @@ impl<'a> RenderApi<'a> {
|
||||||
|
|
||||||
self.add_render_item(&cell, &glyph);
|
self.add_render_item(&cell, &glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME This is a super hacky way to do underlined text. During
|
|
||||||
// a time crunch to release 0.1, this seemed like a really
|
|
||||||
// easy, clean hack.
|
|
||||||
if cell.flags.contains(cell::Flags::UNDERLINE) {
|
|
||||||
let glyph_key = GlyphKey {
|
|
||||||
font_key,
|
|
||||||
size: glyph_cache.font_size,
|
|
||||||
c: '_',
|
|
||||||
};
|
|
||||||
|
|
||||||
let underscore = glyph_cache.get(glyph_key, self);
|
|
||||||
self.add_render_item(&cell, underscore);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,16 +23,17 @@ pub const MAX_ZEROWIDTH_CHARS: usize = 5;
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct Flags: u16 {
|
pub struct Flags: u16 {
|
||||||
const INVERSE = 0b0_0000_0001;
|
const INVERSE = 0b00_0000_0001;
|
||||||
const BOLD = 0b0_0000_0010;
|
const BOLD = 0b00_0000_0010;
|
||||||
const ITALIC = 0b0_0000_0100;
|
const ITALIC = 0b00_0000_0100;
|
||||||
const UNDERLINE = 0b0_0000_1000;
|
const UNDERLINE = 0b00_0000_1000;
|
||||||
const WRAPLINE = 0b0_0001_0000;
|
const WRAPLINE = 0b00_0001_0000;
|
||||||
const WIDE_CHAR = 0b0_0010_0000;
|
const WIDE_CHAR = 0b00_0010_0000;
|
||||||
const WIDE_CHAR_SPACER = 0b0_0100_0000;
|
const WIDE_CHAR_SPACER = 0b00_0100_0000;
|
||||||
const DIM = 0b0_1000_0000;
|
const DIM = 0b00_1000_0000;
|
||||||
const DIM_BOLD = 0b0_1000_0010;
|
const DIM_BOLD = 0b00_1000_0010;
|
||||||
const HIDDEN = 0b1_0000_0000;
|
const HIDDEN = 0b01_0000_0000;
|
||||||
|
const STRIKEOUT = 0b10_0000_0000;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ impl Cell {
|
||||||
(self.c == ' ' || self.c == '\t')
|
(self.c == ' ' || self.c == '\t')
|
||||||
&& self.extra[0] == ' '
|
&& self.extra[0] == ' '
|
||||||
&& self.bg == Color::Named(NamedColor::Background)
|
&& self.bg == Color::Named(NamedColor::Background)
|
||||||
&& !self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE)
|
&& !self.flags.intersects(Flags::INVERSE | Flags::UNDERLINE | Flags::STRIKEOUT)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -419,7 +419,7 @@ impl<'a> RenderableCellsIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct RenderableCell {
|
pub struct RenderableCell {
|
||||||
/// A _Display_ line (not necessarily an _Active_ line)
|
/// A _Display_ line (not necessarily an _Active_ line)
|
||||||
pub line: Line,
|
pub line: Line,
|
||||||
|
@ -1965,6 +1965,8 @@ impl ansi::Handler for Term {
|
||||||
Attr::CancelUnderline => self.cursor.template.flags.remove(cell::Flags::UNDERLINE),
|
Attr::CancelUnderline => self.cursor.template.flags.remove(cell::Flags::UNDERLINE),
|
||||||
Attr::Hidden => self.cursor.template.flags.insert(cell::Flags::HIDDEN),
|
Attr::Hidden => self.cursor.template.flags.insert(cell::Flags::HIDDEN),
|
||||||
Attr::CancelHidden => self.cursor.template.flags.remove(cell::Flags::HIDDEN),
|
Attr::CancelHidden => self.cursor.template.flags.remove(cell::Flags::HIDDEN),
|
||||||
|
Attr::Strike => self.cursor.template.flags.insert(cell::Flags::STRIKEOUT),
|
||||||
|
Attr::CancelStrike => self.cursor.template.flags.remove(cell::Flags::STRIKEOUT),
|
||||||
_ => {
|
_ => {
|
||||||
debug!("Term got unhandled attr: {:?}", attr);
|
debug!("Term got unhandled attr: {:?}", attr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue