add kerning ligatures
This commit is contained in:
parent
500a8fc6d1
commit
d071d1a1c3
2 changed files with 73 additions and 1 deletions
36
src/attrs.rs
36
src/attrs.rs
|
|
@ -125,6 +125,31 @@ impl From<CacheMetrics> for Metrics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Font features for controlling typographic behavior
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
|
pub struct FontFeatures {
|
||||||
|
/// Kerning adjusts spacing between specific character pairs
|
||||||
|
pub kerning: bool,
|
||||||
|
/// Standard ligatures (fi, fl, etc.)
|
||||||
|
pub standard_ligatures: bool,
|
||||||
|
/// Contextual ligatures (context-dependent ligatures)
|
||||||
|
pub contextual_ligatures: bool,
|
||||||
|
/// Discretionary ligatures (optional stylistic ligatures)
|
||||||
|
pub discretionary_ligatures: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontFeatures {
|
||||||
|
/// Create new font features with default settings
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
kerning: true,
|
||||||
|
standard_ligatures: true,
|
||||||
|
contextual_ligatures: false,
|
||||||
|
discretionary_ligatures: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Text attributes
|
/// Text attributes
|
||||||
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
|
||||||
pub struct Attrs<'a> {
|
pub struct Attrs<'a> {
|
||||||
|
|
@ -137,6 +162,7 @@ pub struct Attrs<'a> {
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
pub cache_key_flags: CacheKeyFlags,
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
pub metrics_opt: Option<CacheMetrics>,
|
pub metrics_opt: Option<CacheMetrics>,
|
||||||
|
pub font_features: FontFeatures,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Attrs<'a> {
|
impl<'a> Attrs<'a> {
|
||||||
|
|
@ -153,6 +179,7 @@ impl<'a> Attrs<'a> {
|
||||||
metadata: 0,
|
metadata: 0,
|
||||||
cache_key_flags: CacheKeyFlags::empty(),
|
cache_key_flags: CacheKeyFlags::empty(),
|
||||||
metrics_opt: None,
|
metrics_opt: None,
|
||||||
|
font_features: FontFeatures::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -204,6 +231,12 @@ impl<'a> Attrs<'a> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set [FontFeatures]
|
||||||
|
pub fn font_features(mut self, font_features: FontFeatures) -> Self {
|
||||||
|
self.font_features = font_features;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if font matches
|
/// Check if font matches
|
||||||
pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
|
pub fn matches(&self, face: &fontdb::FaceInfo) -> bool {
|
||||||
//TODO: smarter way of including emoji
|
//TODO: smarter way of including emoji
|
||||||
|
|
@ -252,6 +285,7 @@ pub struct AttrsOwned {
|
||||||
pub metadata: usize,
|
pub metadata: usize,
|
||||||
pub cache_key_flags: CacheKeyFlags,
|
pub cache_key_flags: CacheKeyFlags,
|
||||||
pub metrics_opt: Option<CacheMetrics>,
|
pub metrics_opt: Option<CacheMetrics>,
|
||||||
|
pub font_features: FontFeatures,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttrsOwned {
|
impl AttrsOwned {
|
||||||
|
|
@ -265,6 +299,7 @@ impl AttrsOwned {
|
||||||
metadata: attrs.metadata,
|
metadata: attrs.metadata,
|
||||||
cache_key_flags: attrs.cache_key_flags,
|
cache_key_flags: attrs.cache_key_flags,
|
||||||
metrics_opt: attrs.metrics_opt,
|
metrics_opt: attrs.metrics_opt,
|
||||||
|
font_features: attrs.font_features,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -278,6 +313,7 @@ impl AttrsOwned {
|
||||||
metadata: self.metadata,
|
metadata: self.metadata,
|
||||||
cache_key_flags: self.cache_key_flags,
|
cache_key_flags: self.cache_key_flags,
|
||||||
metrics_opt: self.metrics_opt,
|
metrics_opt: self.metrics_opt,
|
||||||
|
font_features: self.font_features,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
38
src/shape.rs
38
src/shape.rs
|
|
@ -140,12 +140,48 @@ fn shape_fallback(
|
||||||
let rtl = matches!(buffer.direction(), rustybuzz::Direction::RightToLeft);
|
let rtl = matches!(buffer.direction(), rustybuzz::Direction::RightToLeft);
|
||||||
assert_eq!(rtl, span_rtl);
|
assert_eq!(rtl, span_rtl);
|
||||||
|
|
||||||
|
let attrs = attrs_list.get_span(start_run);
|
||||||
|
|
||||||
|
let mut features = Vec::new();
|
||||||
|
|
||||||
|
if attrs.font_features.kerning {
|
||||||
|
features.push(rustybuzz::Feature::new(
|
||||||
|
rustybuzz::ttf_parser::Tag::from_bytes(b"kern"),
|
||||||
|
1,
|
||||||
|
0..usize::MAX,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrs.font_features.standard_ligatures {
|
||||||
|
features.push(rustybuzz::Feature::new(
|
||||||
|
rustybuzz::ttf_parser::Tag::from_bytes(b"liga"),
|
||||||
|
1,
|
||||||
|
0..usize::MAX,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrs.font_features.contextual_ligatures {
|
||||||
|
features.push(rustybuzz::Feature::new(
|
||||||
|
rustybuzz::ttf_parser::Tag::from_bytes(b"clig"),
|
||||||
|
1,
|
||||||
|
0..usize::MAX,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if attrs.font_features.discretionary_ligatures {
|
||||||
|
features.push(rustybuzz::Feature::new(
|
||||||
|
rustybuzz::ttf_parser::Tag::from_bytes(b"dlig"),
|
||||||
|
1,
|
||||||
|
0..usize::MAX,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let shape_plan = rustybuzz::ShapePlan::new(
|
let shape_plan = rustybuzz::ShapePlan::new(
|
||||||
font.rustybuzz(),
|
font.rustybuzz(),
|
||||||
buffer.direction(),
|
buffer.direction(),
|
||||||
Some(buffer.script()),
|
Some(buffer.script()),
|
||||||
buffer.language().as_ref(),
|
buffer.language().as_ref(),
|
||||||
&[],
|
&features,
|
||||||
);
|
);
|
||||||
let glyph_buffer = rustybuzz::shape_with_plan(font.rustybuzz(), &shape_plan, buffer);
|
let glyph_buffer = rustybuzz::shape_with_plan(font.rustybuzz(), &shape_plan, buffer);
|
||||||
let glyph_infos = glyph_buffer.glyph_infos();
|
let glyph_infos = glyph_buffer.glyph_infos();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue