|
4 | 4 | //! Text shaping implementation using `harfrust`for shaping |
5 | 5 | //! and `icu` for text analysis. |
6 | 6 |
|
| 7 | +use alloc::vec::Vec; |
7 | 8 | use parley_engine::shape::{CharCluster, Coverage}; |
8 | 9 | use parley_engine::{Analysis, AnalysisDataSources, FontInstance, ShapeOptions, Shaper}; |
9 | 10 | use smallvec::SmallVec; |
@@ -73,6 +74,29 @@ pub(crate) fn shape_text<'a, B: Brush>( |
73 | 74 |
|
74 | 75 | let mut inline_box_iter = inline_boxes.iter().peekable(); |
75 | 76 |
|
| 77 | + // Merge font features with letter-spacing ligature suppression. |
| 78 | + // |
| 79 | + // TODO: This allocation is slightly unfortunate (though solvable). It's required currently, |
| 80 | + // because the iterator providing `ShapeOptions` has to provide a borrowed `&'a [FontFeature]`, |
| 81 | + // which cannot be tied to the lifetime of the call to `Iterator::next`. What we'd need is a |
| 82 | + // lending iterator (i.e., we probably just need to let `parley_engine` take some trait |
| 83 | + // providing the items). |
| 84 | + let style_features: &'_ Vec<SmallVec<[FontFeature; 8]>> = &styles |
| 85 | + .iter() |
| 86 | + .map(|style| { |
| 87 | + let style_features = rcx.features(style.font_features).unwrap_or(&[]); |
| 88 | + if !nearly_zero(style.letter_spacing) { |
| 89 | + // Later values override earlier values. |
| 90 | + OPTIONAL_LIGATURES_OFF |
| 91 | + .into_iter() |
| 92 | + .chain(style_features.iter().copied()) |
| 93 | + .collect() |
| 94 | + } else { |
| 95 | + style_features.iter().copied().collect() |
| 96 | + } |
| 97 | + }) |
| 98 | + .collect(); |
| 99 | + |
76 | 100 | // Split when shaping-relevant style properties change and at inline boxes. |
77 | 101 | let items = { |
78 | 102 | // TODO: we currently walk characters here, but we could instead just walk boundaries of |
@@ -147,7 +171,7 @@ pub(crate) fn shape_text<'a, B: Brush>( |
147 | 171 | options: ShapeOptions { |
148 | 172 | language: item_style.locale, |
149 | 173 | font_size: item_style.font_size, |
150 | | - features: rcx.features(item_style.font_features).unwrap_or(&[]), |
| 174 | + features: &style_features[item_style_index as usize], |
151 | 175 | variations: rcx.variations(item_style.font_variations).unwrap_or(&[]), |
152 | 176 | char_style_indices, |
153 | 177 | }, |
|
0 commit comments