Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Font Ligatures using harfbuzz #5696

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 37 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion alacritty/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,13 @@ serde_json = "1"
glutin = { version = "0.28.0", default-features = false, features = ["serde"] }
notify = "4"
parking_lot = "0.11.0"
crossfont = { version = "0.3.1", features = ["force_system_fontconfig"] }
crossfont = { git = "https://github.com/fee1-dead/crossfont", features = ["force_system_fontconfig"] }
copypasta = { version = "0.7.0", default-features = false }
libc = "0.2"
unicode-width = "0.1"
bitflags = "1"
dirs = "3.0.1"
harfbuzz_rs = "2.0.1"

[dev-dependencies]
clap = "2.33.3"
Expand Down
20 changes: 19 additions & 1 deletion alacritty/src/config/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::config::ui_config::Delta;
/// field in this struct. It might be nice in the future to have defaults for
/// each value independently. Alternatively, maybe erroring when the user
/// doesn't provide complete config is Ok.
#[derive(ConfigDeserialize, Default, Debug, Clone, PartialEq, Eq)]
#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)]
pub struct Font {
/// Extra spacing per character.
pub offset: Delta<i8>,
Expand All @@ -24,6 +24,8 @@ pub struct Font {

pub use_thin_strokes: bool,

pub ligatures: bool,

/// Normal font face.
normal: FontDescription,

Expand Down Expand Up @@ -72,6 +74,22 @@ impl Font {
}
}

impl Default for Font {
fn default() -> Self {
Self {
offset: Default::default(),
glyph_offset: Default::default(),
use_thin_strokes: false,
ligatures: true,
normal: Default::default(),
bold: Default::default(),
italic: Default::default(),
bold_italic: Default::default(),
size: Default::default(),
}
}
}

/// Description of the normal font.
#[derive(ConfigDeserialize, Debug, Clone, PartialEq, Eq)]
pub struct FontDescription {
Expand Down
68 changes: 42 additions & 26 deletions alacritty/src/display/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ use crate::display::meter::Meter;
use crate::display::window::Window;
use crate::event::{Mouse, SearchState};
use crate::message_bar::{MessageBuffer, MessageType};
use crate::renderer::rects::{RenderLines, RenderRect};
use crate::renderer::rects::RenderRect;
use crate::renderer::{self, GlyphCache, QuadRenderer};
use crate::text_run::{TextRun, TextRunIter};

pub mod content;
pub mod cursor;
Expand Down Expand Up @@ -357,8 +358,8 @@ impl Display {
info!("Initializing glyph cache...");
let init_start = Instant::now();

let cache =
renderer.with_loader(|mut api| GlyphCache::new(rasterizer, &font, &mut api))?;
let cache = renderer
.with_loader(|mut api| GlyphCache::new(rasterizer, &font, &mut api, config))?;

let stop = init_start.elapsed();
let stop_f = stop.as_secs() as f64 + f64::from(stop.subsec_nanos()) / 1_000_000_000f64;
Expand Down Expand Up @@ -479,14 +480,21 @@ impl Display {
config: &UiConfig,
search_state: &SearchState,
) {
let highlighted_hint = self.highlighted_hint.as_ref().map(|m| m.bounds.clone());
let vi_highlighted_hint = self.vi_highlighted_hint.as_ref().map(|m| m.bounds.clone());
// Collect renderable content before the terminal is dropped.
let mut content = RenderableContent::new(config, self, &terminal, search_state);
let mut grid_cells = Vec::new();
for cell in &mut content {
grid_cells.push(cell);
}
let background_color = content.color(NamedColor::Background as usize);
let display_offset = content.display_offset();
let grid_text_runs: Vec<TextRun> = {
let mut vec = Vec::with_capacity(terminal.screen_lines() * 2);
vec.extend(TextRunIter::from_content(
&mut content,
highlighted_hint,
vi_highlighted_hint,
));
vec
};
let cursor = content.cursor();

let cursor_point = terminal.grid().cursor.point;
Expand All @@ -507,7 +515,7 @@ impl Display {
api.clear(background_color);
});

let mut lines = RenderLines::new();
let mut rects: Vec<RenderRect> = Vec::new();

// Draw grid.
{
Expand All @@ -518,30 +526,38 @@ impl Display {
self.renderer.set_viewport(&size_info);

let glyph_cache = &mut self.glyph_cache;
let highlighted_hint = &self.highlighted_hint;
let vi_highlighted_hint = &self.vi_highlighted_hint;

self.renderer.with_api(config, &size_info, |mut api| {
// Iterate over all non-empty cells in the grid.
for mut cell in grid_cells {
// Underline hints hovered by mouse or vi mode cursor.
let point = viewport_to_point(display_offset, cell.point);
if highlighted_hint.as_ref().map_or(false, |h| h.bounds.contains(&point))
|| vi_highlighted_hint.as_ref().map_or(false, |h| h.bounds.contains(&point))
{
cell.flags.insert(Flags::UNDERLINE);
for text_run in grid_text_runs {
if text_run.flags.contains(Flags::UNDERLINE) {
let underline_metrics = (
metrics.descent,
metrics.underline_position,
metrics.underline_thickness,
);
rects.push(RenderRect::from_text_run(
&text_run,
underline_metrics,
&size_info,
));
}

// Update underline/strikeout.
lines.update(&cell);

// Draw the cell.
api.render_cell(cell, glyph_cache);
if text_run.flags.contains(Flags::STRIKEOUT) {
let strikeout_metrics = (
metrics.descent,
metrics.strikeout_position,
metrics.strikeout_thickness,
);
rects.push(RenderRect::from_text_run(
&text_run,
strikeout_metrics,
&size_info,
));
}
api.render_text_run(text_run, glyph_cache);
}
});
}

let mut rects = lines.rects(&metrics, &size_info);

if let Some(vi_mode_cursor) = vi_mode_cursor {
// Indicate vi mode by showing the cursor's position in the top right corner.
let vi_point = vi_mode_cursor.point;
Expand Down
1 change: 1 addition & 0 deletions alacritty/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ mod message_bar;
mod panic;
mod renderer;
mod scheduler;
mod text_run;
mod window_context;

mod gl {
Expand Down