mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
fonts: allow shaping with additional paragraph context
we don't really use this yet, except internally when we do fallback
This commit is contained in:
parent
c737fb66df
commit
4ca1378f1f
@ -4,6 +4,7 @@ use freetype;
|
||||
pub use harfbuzz::*;
|
||||
|
||||
use anyhow::{ensure, Error};
|
||||
use std::ops::Range;
|
||||
use std::os::raw::c_char;
|
||||
use std::{mem, slice};
|
||||
|
||||
@ -121,7 +122,6 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_direction(&mut self, direction: hb_direction_t) {
|
||||
unsafe {
|
||||
hb_buffer_set_direction(self.buf, direction);
|
||||
@ -148,20 +148,24 @@ impl Buffer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_utf8(&mut self, buf: &[u8]) {
|
||||
#[allow(dead_code)]
|
||||
pub fn reverse(&mut self) {
|
||||
unsafe {
|
||||
hb_buffer_add_utf8(
|
||||
self.buf,
|
||||
buf.as_ptr() as *const c_char,
|
||||
buf.len() as i32,
|
||||
0,
|
||||
buf.len() as i32,
|
||||
);
|
||||
hb_buffer_reverse_clusters(self.buf);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_str(&mut self, s: &str) {
|
||||
self.add_utf8(s.as_bytes())
|
||||
pub fn add_str(&mut self, paragraph: &str, range: Range<usize>) {
|
||||
let bytes = paragraph.as_bytes();
|
||||
unsafe {
|
||||
hb_buffer_add_utf8(
|
||||
self.buf,
|
||||
bytes.as_ptr() as *const c_char,
|
||||
bytes.len() as i32,
|
||||
range.start as u32,
|
||||
(range.end - range.start) as i32,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns glyph information. This is only valid after calling
|
||||
|
@ -11,6 +11,7 @@ use config::{
|
||||
use rangeset::RangeSet;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::ops::Range;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::mpsc::{channel, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -116,6 +117,7 @@ impl LoadedFont {
|
||||
text: &str,
|
||||
presentation: Option<Presentation>,
|
||||
direction: Direction,
|
||||
range: Option<Range<usize>>,
|
||||
) -> anyhow::Result<Vec<GlyphInfo>> {
|
||||
loop {
|
||||
let (tx, rx) = channel();
|
||||
@ -128,6 +130,7 @@ impl LoadedFont {
|
||||
|_| {},
|
||||
presentation,
|
||||
direction,
|
||||
range.clone(),
|
||||
) {
|
||||
Ok(tuple) => tuple,
|
||||
Err(err) if err.downcast_ref::<ClearShapeCache>().is_some() => {
|
||||
@ -152,6 +155,7 @@ impl LoadedFont {
|
||||
filter_out_synthetic: FS,
|
||||
presentation: Option<Presentation>,
|
||||
direction: Direction,
|
||||
range: Option<Range<usize>>,
|
||||
) -> anyhow::Result<Vec<GlyphInfo>> {
|
||||
let (_async_resolve, res) = self.shape_impl(
|
||||
text,
|
||||
@ -159,6 +163,7 @@ impl LoadedFont {
|
||||
filter_out_synthetic,
|
||||
presentation,
|
||||
direction,
|
||||
range,
|
||||
)?;
|
||||
Ok(res)
|
||||
}
|
||||
@ -170,6 +175,7 @@ impl LoadedFont {
|
||||
filter_out_synthetic: FS,
|
||||
presentation: Option<Presentation>,
|
||||
direction: Direction,
|
||||
range: Option<Range<usize>>,
|
||||
) -> anyhow::Result<(bool, Vec<GlyphInfo>)> {
|
||||
let mut no_glyphs = vec![];
|
||||
|
||||
@ -193,6 +199,7 @@ impl LoadedFont {
|
||||
&mut no_glyphs,
|
||||
presentation,
|
||||
direction,
|
||||
range,
|
||||
);
|
||||
|
||||
no_glyphs.retain(|&c| c != '\u{FE0F}' && c != '\u{FE0E}');
|
||||
|
@ -8,6 +8,7 @@ use log::error;
|
||||
use ordered_float::NotNan;
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::ops::Range;
|
||||
use termwiz::cell::{unicode_column_width, Presentation};
|
||||
use thiserror::Error;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
@ -187,6 +188,7 @@ impl HarfbuzzShaper {
|
||||
no_glyphs: &mut Vec<char>,
|
||||
presentation: Option<Presentation>,
|
||||
direction: Direction,
|
||||
range: Range<usize>,
|
||||
) -> anyhow::Result<Vec<GlyphInfo>> {
|
||||
let mut buf = harfbuzz::Buffer::new()?;
|
||||
// We deliberately omit setting the script and leave it to harfbuzz
|
||||
@ -201,7 +203,7 @@ impl HarfbuzzShaper {
|
||||
});
|
||||
buf.set_language(self.lang);
|
||||
|
||||
buf.add_str(s);
|
||||
buf.add_str(s, range.clone());
|
||||
let mut cluster_to_len = vec![];
|
||||
for c in s.chars() {
|
||||
let len = c.len_utf8();
|
||||
@ -288,6 +290,7 @@ impl HarfbuzzShaper {
|
||||
no_glyphs,
|
||||
None,
|
||||
direction,
|
||||
range,
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -370,7 +373,8 @@ impl HarfbuzzShaper {
|
||||
.map(|info| info.cluster + info.len)
|
||||
.max()
|
||||
.unwrap();
|
||||
let substr = &s[cluster_start..cluster_end];
|
||||
let sub_range = cluster_start..cluster_end;
|
||||
let substr = &s[sub_range.clone()];
|
||||
|
||||
let incomplete = infos.iter().find(|info| info.codepoint == 0).is_some();
|
||||
|
||||
@ -386,12 +390,13 @@ impl HarfbuzzShaper {
|
||||
|
||||
let mut shape = match self.do_shape(
|
||||
font_idx + 1,
|
||||
substr,
|
||||
s,
|
||||
font_size,
|
||||
dpi,
|
||||
no_glyphs,
|
||||
presentation,
|
||||
direction,
|
||||
sub_range.clone(),
|
||||
) {
|
||||
Ok(shape) => Ok(shape),
|
||||
Err(e) => {
|
||||
@ -404,14 +409,11 @@ impl HarfbuzzShaper {
|
||||
no_glyphs,
|
||||
presentation,
|
||||
direction,
|
||||
0..substr.len(),
|
||||
)
|
||||
}
|
||||
}?;
|
||||
|
||||
// Fixup the cluster member to match our current offset
|
||||
for mut info in &mut shape {
|
||||
info.cluster += cluster_start as u32;
|
||||
}
|
||||
cluster.append(&mut shape);
|
||||
continue;
|
||||
}
|
||||
@ -485,10 +487,22 @@ impl FontShaper for HarfbuzzShaper {
|
||||
no_glyphs: &mut Vec<char>,
|
||||
presentation: Option<Presentation>,
|
||||
direction: Direction,
|
||||
range: Option<Range<usize>>,
|
||||
) -> anyhow::Result<Vec<GlyphInfo>> {
|
||||
let range = range.unwrap_or_else(|| 0..text.len());
|
||||
|
||||
log::trace!("shape byte_len={} `{}`", text.len(), text.escape_debug());
|
||||
let start = std::time::Instant::now();
|
||||
let result = self.do_shape(0, text, size, dpi, no_glyphs, presentation, direction);
|
||||
let result = self.do_shape(
|
||||
0,
|
||||
text,
|
||||
size,
|
||||
dpi,
|
||||
no_glyphs,
|
||||
presentation,
|
||||
direction,
|
||||
range,
|
||||
);
|
||||
metrics::histogram!("shape.harfbuzz", start.elapsed());
|
||||
/*
|
||||
if let Ok(glyphs) = &result {
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::parser::ParsedFont;
|
||||
use crate::units::PixelLength;
|
||||
use std::ops::Range;
|
||||
use termwiz::cell::Presentation;
|
||||
|
||||
pub mod harfbuzz;
|
||||
@ -81,6 +82,7 @@ pub trait FontShaper {
|
||||
no_glyphs: &mut Vec<char>,
|
||||
presentation: Option<termwiz::cell::Presentation>,
|
||||
direction: Direction,
|
||||
range: Option<Range<usize>>,
|
||||
) -> anyhow::Result<Vec<GlyphInfo>>;
|
||||
|
||||
/// Compute the font metrics for the preferred font
|
||||
|
@ -688,7 +688,12 @@ pub fn run_ls_fonts(config: config::ConfigHandle, cmd: &LsFontsCommand) -> anyho
|
||||
let style = font_config.match_style(&config, &cluster.attrs);
|
||||
let font = font_config.resolve_font(style)?;
|
||||
let infos = font
|
||||
.blocking_shape(&cluster.text, Some(cluster.presentation), cluster.direction)
|
||||
.blocking_shape(
|
||||
&cluster.text,
|
||||
Some(cluster.presentation),
|
||||
cluster.direction,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
// We must grab the handles after shaping, so that we get the
|
||||
|
@ -547,6 +547,7 @@ impl super::TermWindow {
|
||||
BlockKey::filter_out_synthetic,
|
||||
element.presentation,
|
||||
direction,
|
||||
None,
|
||||
)?;
|
||||
let mut computed_cells = vec![];
|
||||
let mut glyph_cache = context.gl_state.glyph_cache.borrow_mut();
|
||||
|
@ -2686,6 +2686,7 @@ impl super::TermWindow {
|
||||
BlockKey::filter_out_synthetic,
|
||||
Some(cluster.presentation),
|
||||
cluster.direction,
|
||||
None, // FIXME: need more paragraph context
|
||||
) {
|
||||
Ok(info) => {
|
||||
let glyphs = self.glyph_infos_to_glyphs(
|
||||
|
@ -463,6 +463,7 @@ impl ConceptFrame {
|
||||
},
|
||||
None,
|
||||
wezterm_bidi::Direction::LeftToRight,
|
||||
None,
|
||||
)
|
||||
.ok()?;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user